Move the builder page to the main branch.
|
@ -1 +1,6 @@
|
||||||
node_modules
|
node_modules
|
||||||
|
gh-pages/public/social-likes
|
||||||
|
gh-pages/public/build
|
||||||
|
gh-pages/public/src
|
||||||
|
gh-pages/public/index.html
|
||||||
|
gh-pages/public/ru/index.html
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"browser": true,
|
||||||
|
"jquery": true,
|
||||||
|
"white": false,
|
||||||
|
"smarttabs": true,
|
||||||
|
"eqeqeq": true,
|
||||||
|
"immed": true,
|
||||||
|
"latedef": false,
|
||||||
|
"newcap": true,
|
||||||
|
"undef": true,
|
||||||
|
"trailing": true,
|
||||||
|
"esnext": true,
|
||||||
|
"camelcase": true,
|
||||||
|
"bitwise": true,
|
||||||
|
"noempty": true,
|
||||||
|
"unused": "vars",
|
||||||
|
"strict": true,
|
||||||
|
"globals": {
|
||||||
|
"Modernizr": false,
|
||||||
|
"tamia": false,
|
||||||
|
"Component": false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
module.exports = function(grunt) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
grunt.file.expand('../node_modules/grunt-*/tasks').forEach(grunt.loadTasks);
|
||||||
|
|
||||||
|
var debug = !!grunt.option('debug');
|
||||||
|
var prefix = debug ? '' : '/social-likes/';
|
||||||
|
|
||||||
|
grunt.initConfig({
|
||||||
|
pkg: grunt.file.readJSON('../package.json'),
|
||||||
|
banner: '/* Author: Artem Sapegin, http://sapegin.me, <%= grunt.template.today("yyyy") %> */\n',
|
||||||
|
modernizr: {
|
||||||
|
main: {
|
||||||
|
devFile: 'vendor/modernizr.js',
|
||||||
|
outputFile: 'public/build/modernizr.js',
|
||||||
|
dest: 'public/build/modernizr.js',
|
||||||
|
extra: {
|
||||||
|
load: false
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
src: ['public/build/scripts.js', 'public/build/styles.css']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
jshint: {
|
||||||
|
all: ['js/main.js']
|
||||||
|
},
|
||||||
|
concat: {
|
||||||
|
main: {
|
||||||
|
src: [
|
||||||
|
'js/mylibs/htmlhl.js',
|
||||||
|
'js/libs/doT.min.js',
|
||||||
|
'js/libs/jszip.js',
|
||||||
|
'js/libs/jszip-deflate.js',
|
||||||
|
'js/libs/store+json2.min.js',
|
||||||
|
'tamia/vendor/*.js',
|
||||||
|
'tamia/tamia/tamia.js',
|
||||||
|
'js/main.js'
|
||||||
|
],
|
||||||
|
dest: 'public/build/scripts.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uglify: {
|
||||||
|
main: {
|
||||||
|
options: {
|
||||||
|
banner: '<%= banner %>',
|
||||||
|
compress: {
|
||||||
|
global_defs: {
|
||||||
|
DEBUG: debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
'<%= concat.main.dest %>': '<%= concat.main.dest %>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stylus: {
|
||||||
|
options: {
|
||||||
|
'include css': true,
|
||||||
|
urlfunc: 'embedurl',
|
||||||
|
banner: '<%= banner %>',
|
||||||
|
define: {
|
||||||
|
DEBUG: debug
|
||||||
|
},
|
||||||
|
paths: ['tamia'],
|
||||||
|
use: [
|
||||||
|
function() {
|
||||||
|
return (require('autoprefixer-stylus'))({browsers: ['last 2 versions', 'ie 8', 'ie 9']});
|
||||||
|
}, debug || (require('csso-stylus'))
|
||||||
|
]
|
||||||
|
},
|
||||||
|
compile: {
|
||||||
|
files: {
|
||||||
|
'public/build/styles.css': 'styles/index.styl'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sweet: {
|
||||||
|
content_dir: 'content',
|
||||||
|
publish_dir: 'public',
|
||||||
|
templates_dir: 'templates',
|
||||||
|
default_template_id: 'template',
|
||||||
|
langs: ['ru', 'en'],
|
||||||
|
root_lang: 'en',
|
||||||
|
url_prefixes: {
|
||||||
|
ru: prefix + 'ru/',
|
||||||
|
en: prefix
|
||||||
|
},
|
||||||
|
uri_prefixes: {
|
||||||
|
ru: prefix + 'ru/',
|
||||||
|
en: prefix
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
modernizr: {
|
||||||
|
path: 'public/build/modernizr.js',
|
||||||
|
href: prefix + 'build/modernizr.js?{version}'
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
path: 'public/build/styles.css',
|
||||||
|
href: prefix + 'build/styles.css?{version}'
|
||||||
|
},
|
||||||
|
js: {
|
||||||
|
path: '<%= concat.main.dest %>',
|
||||||
|
href: prefix + 'build/scripts.js?{version}'
|
||||||
|
},
|
||||||
|
sljs: {
|
||||||
|
path: 'public/src/social-likes.min.js',
|
||||||
|
href: prefix + 'src/social-likes.min.js?{version}'
|
||||||
|
},
|
||||||
|
slcss_classic: {
|
||||||
|
path: 'public/src/social-likes_classic.css',
|
||||||
|
href: prefix + 'src/social-likes_classic.css?{version}'
|
||||||
|
},
|
||||||
|
slcss_flat: {
|
||||||
|
path: 'public/src/social-likes_flat.css',
|
||||||
|
href: prefix + 'src/social-likes_flat.css?{version}'
|
||||||
|
},
|
||||||
|
slcss_birman: {
|
||||||
|
path: 'public/src/social-likes_birman.css',
|
||||||
|
href: prefix + 'src/social-likes_birman.css?{version}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
replace: {
|
||||||
|
version: {
|
||||||
|
files: {
|
||||||
|
'public/index.html': 'public/index.html',
|
||||||
|
'public/ru/index.html': 'public/ru/index.html'
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
match: /(<!\-\-VERSION\-\->).*?(<!\-\-\/VERSION\-\->)/,
|
||||||
|
replacement: '$1<%= pkg.version %>$2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
connect: {
|
||||||
|
server: {
|
||||||
|
options: {
|
||||||
|
port: 9000,
|
||||||
|
base: '.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
livereload: {
|
||||||
|
options: {
|
||||||
|
livereload: true
|
||||||
|
},
|
||||||
|
files: ['<%= concat.main.dest %>', 'public/build/styles.css']
|
||||||
|
},
|
||||||
|
concat: {
|
||||||
|
options: {
|
||||||
|
atBegin: true
|
||||||
|
},
|
||||||
|
files: '<%= concat.main.src %>',
|
||||||
|
tasks: 'concat'
|
||||||
|
},
|
||||||
|
stylus: {
|
||||||
|
options: {
|
||||||
|
atBegin: true
|
||||||
|
},
|
||||||
|
files: 'styles/**',
|
||||||
|
tasks: 'stylus'
|
||||||
|
},
|
||||||
|
sweet: {
|
||||||
|
options: {
|
||||||
|
atBegin: true
|
||||||
|
},
|
||||||
|
files: ['content/**', 'templates/**'],
|
||||||
|
tasks: 'sweet'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'stylus', 'modernizr', 'sweet', 'replace']);
|
||||||
|
};
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"sites": [
|
||||||
|
{
|
||||||
|
"id": "facebook",
|
||||||
|
"name": "Facebook",
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "twitter",
|
||||||
|
"name": "Twitter",
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "plusone",
|
||||||
|
"name": "Google+",
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mailru",
|
||||||
|
"name": "Мой мир",
|
||||||
|
"checked": true,
|
||||||
|
"langs": ["ru"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vkontakte",
|
||||||
|
"name": "Вконтакте",
|
||||||
|
"checked": true,
|
||||||
|
"langs": ["ru"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "odnoklassniki",
|
||||||
|
"checked": true,
|
||||||
|
"name": "Одноклассники",
|
||||||
|
"langs": ["ru"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pinterest",
|
||||||
|
"name": "Pinterest"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
name: Social Likes
|
||||||
|
title: Social Likes: beautiful social like buttons with jQuery
|
||||||
|
description: Single style social like buttons with counters for jQuery: Facebook, Twitter, Google+, Pinterest and also popular <a href="/social-likes/ru/">Russian social networks</a>.
|
||||||
|
descriptionHead: Single style buttons with like counters: Facebook, Twitter, Google+, Pinterest and also popular Russian social networks.
|
||||||
|
translationLink: /social-likes/ru/
|
||||||
|
translationTitle: По-русски
|
||||||
|
builderSkin: Skin
|
||||||
|
builderSkinClassic: Classic
|
||||||
|
builderSkinFlat: Flat β
|
||||||
|
builderSkinBirman: Birman β
|
||||||
|
builderType: Look
|
||||||
|
builderTypeHorizontal: Horizontal
|
||||||
|
builderTypeVertical: Vertical
|
||||||
|
builderTypeSingle: Single button
|
||||||
|
builderCounters: Show counters
|
||||||
|
builderLight: Light style
|
||||||
|
builderSites: Websites
|
||||||
|
builderUrl: URL
|
||||||
|
builderUrlHelp: When buttons used on different page
|
||||||
|
builderTitle: Title
|
||||||
|
builderTitleHelp: When differs from current page’s title
|
||||||
|
builderTwitterVia: Twitter Via
|
||||||
|
builderTwitterViaHelp: Username
|
||||||
|
builderTwitterRelated: Twitter Related
|
||||||
|
builderTwitterRelatedHelp: Username:Description
|
||||||
|
builderPinterestMedia: Image URL
|
||||||
|
builderPinterestMediaHelp: Image URL for Pinterest (required)
|
||||||
|
titleFacebook: Share link on Facebook
|
||||||
|
titleTwitter: Share link on Twitter
|
||||||
|
titlePlusone: Share link on Google+
|
||||||
|
titlePinterest: Share image on Pinterest
|
||||||
|
singleTitle: Share
|
||||||
|
downloadArchive: Download the Buttons
|
||||||
|
or: or
|
||||||
|
browseCode: view source
|
||||||
|
onGitHub: on GitHub
|
||||||
|
archiveContains: Version <a href="https://github.com/sapegin/social-likes/blob/master/Changelog.md"><!--VERSION--><!--/VERSION--></a>. Archive contains all you need to use like buttons with chosen options.
|
||||||
|
archiveFooter: <a href="http://sapegin.github.com/social-likes/">Social Likes</a> — <a href="https://github.com/sapegin/social-likes/Readme.md">documentation</a>
|
||||||
|
docs: <a href="https://github.com/sapegin/social-likes/blob/master/Readme.md">Documentation</a> and advanced customization examples.<br>Report bugs <a href="https://github.com/sapegin/social-likes/issues">on GitHub</a>.
|
||||||
|
footer: © 2014 <a href="https://github.com/sapegin">Artem Sapegin</a> and contributors. Flat skin: <a href="http://genn.org/">Genn Osypenko</a>, Birman skin: <a href="http://ilyabirman.net/">Ilya Birman</a>
|
|
@ -0,0 +1,39 @@
|
||||||
|
name: Social Likes
|
||||||
|
title: Social Likes — красивые кнопки «лайков» социальных сетей с использованием jQuery
|
||||||
|
description: Красивые кнопки «лайков» со счётчиками в едином стиле для социальных сетей: Facebook, Twitter, Вконтакте, Одноклассники, Мой мир, Google+ и Pinterest. Кнопки уже используют <a href="http://www.snob.ru/">Сноб</a>, <a href="http://sberbank.ru/">Сбербанк</a>, <a href="http://blogengine.ru/blogs/">блоги на Эгее</a> и многие другие.
|
||||||
|
translationLink: /social-likes/
|
||||||
|
translationTitle: In English
|
||||||
|
builderSkin: Скин
|
||||||
|
builderSkinClassic: Классический
|
||||||
|
builderSkinFlat: Плоский β
|
||||||
|
builderSkinBirman: Бирман β
|
||||||
|
builderType: Вид
|
||||||
|
builderTypeHorizontal: Горизонтальный
|
||||||
|
builderTypeVertical: Вертикальный
|
||||||
|
builderTypeSingle: Одной кнопкой
|
||||||
|
builderCounters: Счётчики
|
||||||
|
builderLight: Лёгкий стиль
|
||||||
|
builderSites: Сайты
|
||||||
|
builderUrl: Адрес страницы
|
||||||
|
builderUrlHelp: Если отличается от адреса страницы, где размещены кнопки
|
||||||
|
builderTitle: Название
|
||||||
|
builderTitleHelp: Если отличается от заголовка страницы, где размещены кнопки
|
||||||
|
builderTwitterVia: Twitter Via
|
||||||
|
builderTwitterViaHelp: Имя в Твиттере
|
||||||
|
builderTwitterRelated: Twitter Related
|
||||||
|
builderTwitterRelatedHelp: Имя:Описание
|
||||||
|
builderPinterestMedia: URL картинки
|
||||||
|
builderPinterestMediaHelp: URL картинки для Пинтереста (обязательно)
|
||||||
|
titleFacebook: Поделиться ссылкой на Фейсбуке
|
||||||
|
titleTwitter: Поделиться ссылкой в Твиттере
|
||||||
|
titlePlusone: Поделиться ссылкой в Гугл-плюсе
|
||||||
|
titlePinterest: Поделиться картинкой на Пинтересте
|
||||||
|
singleTitle: Поделиться
|
||||||
|
downloadArchive: Скачать кнопки
|
||||||
|
or: или
|
||||||
|
browseCode: посмотреть код
|
||||||
|
onGitHub: на Гитхабе
|
||||||
|
archiveContains: Версия <a href="https://github.com/sapegin/social-likes/blob/master/Changelog.md"><!--VERSION--><!--/VERSION--></a>. В архиве есть всё необходимое для подключения кнопок с выбранными параметрами.
|
||||||
|
archiveFooter: <a href="http://sapegin.github.com/social-likes/">Social Likes</a> — <a href="https://github.com/sapegin/social-likes/Readme.md">документация</a>
|
||||||
|
docs: <a href="https://github.com/sapegin/social-likes/blob/master/Readme.md">Документация</a>, примеры настройки и расширения.<br>Об ошибках пишите <a href="https://github.com/sapegin/social-likes/issues">на Гитхаб</a>.
|
||||||
|
footer: © 2014 <a href="https://github.com/sapegin">Артём Сапегин</a> и другие. Плоский скин: <a href="http://genn.org/">Гена Осипенко</a>, скин Бирмана: <a href="http://ilyabirman.ru/">Илья Бирман</a>
|
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 8.0 KiB |
|
@ -0,0 +1,7 @@
|
||||||
|
// Laura Doktorova https://github.com/olado/doT
|
||||||
|
(function(){function o(){var b={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},a=/&(?!#?\w+;)|<|>|"|'|\//g;return function(f){return f?f.toString().replace(a,function(g){return b[g]||g}):f}}function p(b,a,f){return(typeof a==="string"?a:a.toString()).replace(b.define||h,function(g,e,c,i){if(e.indexOf("def.")===0)e=e.substring(4);if(!(e in f))if(c===":")f[e]=i;else eval("def['"+e+"']="+i);return""}).replace(b.use||h,function(g,e){var c=eval(e);return c?p(b,c,f):c})}function l(b){return b.replace(/\\('|\\)/g,
|
||||||
|
"$1").replace(/[\r\t\n]/g," ")}var j={version:"0.2.0",templateSettings:{evaluate:/\{\{([\s\S]+?)\}\}/g,interpolate:/\{\{=([\s\S]+?)\}\}/g,encode:/\{\{!([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,conditional:/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,varname:"it",strip:true,append:true,selfcontained:false},template:undefined,compile:undefined},m=function(){return this||(0,eval)("this")}();
|
||||||
|
if(typeof module!=="undefined"&&module.exports)module.exports=j;else if(typeof define==="function"&&define.amd)define(function(){return j});else m.doT=j;m.encodeHTML=o();var q={append:{start:"'+(",end:")+'",startencode:"'+encodeHTML("},split:{start:"';out+=(",end:");out+='",startencode:"';out+=encodeHTML("}},h=/$^/;j.template=function(b,a,f){a=a||j.templateSettings;var g=a.append?q.append:q.split,e,c=0,i;if(a.use||a.define){var r=m.def;m.def=f||{};b=p(a,b,m.def);m.def=r}b=("var out='"+(a.strip?b.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g,
|
||||||
|
" ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):b).replace(/'|\\/g,"\\$&").replace(a.interpolate||h,function(n,d){return g.start+l(d)+g.end}).replace(a.encode||h,function(n,d){e=true;return g.startencode+l(d)+g.end}).replace(a.conditional||h,function(n,d,k){return d?k?"';}else if("+l(k)+"){out+='":"';}else{out+='":k?"';if("+l(k)+"){out+='":"';}out+='"}).replace(a.iterate||h,function(n,d,k,s){if(!d)return"';} } out+='";c+=1;i=s||"i"+c;d=l(d);return"';var arr"+c+"="+d+";if(arr"+c+"){var "+k+","+i+"=-1,l"+
|
||||||
|
c+"=arr"+c+".length-1;while("+i+"<l"+c+"){"+k+"=arr"+c+"["+i+"+=1];out+='"}).replace(a.evaluate||h,function(n,d){return"';"+l(d)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|}|^|{)out\+='';/g,"$1").replace(/\+''/g,"").replace(/(\s|;|}|^|{)out\+=''\+/g,"$1out+=");if(e&&a.selfcontained)b="var encodeHTML=("+o.toString()+"());"+b;try{return new Function(a.varname,b)}catch(t){typeof console!=="undefined"&&console.log("Could not create a template function: "+
|
||||||
|
b);throw t;}};j.compile=function(b,a){return j.template(b,null,a)}})();
|
|
@ -0,0 +1,735 @@
|
||||||
|
/**
|
||||||
|
|
||||||
|
JSZip - A Javascript class for generating and reading zip files
|
||||||
|
<http://stuartk.com/jszip>
|
||||||
|
|
||||||
|
(c) 2009-2012 Stuart Knightley <stuart [at] stuartk.com>
|
||||||
|
Dual licenced under the MIT license or GPLv3. See LICENSE.markdown.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
zip = new JSZip();
|
||||||
|
zip.file("hello.txt", "Hello, World!").add("tempfile", "nothing");
|
||||||
|
zip.folder("images").file("smile.gif", base64Data, {base64: true});
|
||||||
|
zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")});
|
||||||
|
zip.remove("tempfile");
|
||||||
|
|
||||||
|
base64zip = zip.generate();
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation a of zip file in js
|
||||||
|
* @constructor
|
||||||
|
* @param {String=} data the data to load, if any (optional).
|
||||||
|
* @param {Object=} options the options for creating this objects (optional).
|
||||||
|
*/
|
||||||
|
var JSZip = function(data, options) {
|
||||||
|
// object containing the files :
|
||||||
|
// {
|
||||||
|
// "folder/" : {...},
|
||||||
|
// "folder/data.txt" : {...}
|
||||||
|
// }
|
||||||
|
this.files = {};
|
||||||
|
|
||||||
|
// Where we are in the hierarchy
|
||||||
|
this.root = "";
|
||||||
|
|
||||||
|
if(data) {
|
||||||
|
this.load(data, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JSZip.signature = {
|
||||||
|
LOCAL_FILE_HEADER : "\x50\x4b\x03\x04",
|
||||||
|
CENTRAL_FILE_HEADER : "\x50\x4b\x01\x02",
|
||||||
|
CENTRAL_DIRECTORY_END : "\x50\x4b\x05\x06",
|
||||||
|
ZIP64_CENTRAL_DIRECTORY_LOCATOR : "\x50\x4b\x06\x07",
|
||||||
|
ZIP64_CENTRAL_DIRECTORY_END : "\x50\x4b\x06\x06",
|
||||||
|
DATA_DESCRIPTOR : "\x50\x4b\x07\x08"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default properties for a new file
|
||||||
|
JSZip.defaults = {
|
||||||
|
base64: false,
|
||||||
|
binary: false,
|
||||||
|
dir: false,
|
||||||
|
date: null
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
JSZip.prototype = (function ()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A simple object representing a file in the zip file.
|
||||||
|
* @constructor
|
||||||
|
* @param {string} name the name of the file
|
||||||
|
* @param {string} data the data
|
||||||
|
* @param {Object} options the options of the file
|
||||||
|
*/
|
||||||
|
var ZipObject = function (name, data, options) {
|
||||||
|
this.name = name;
|
||||||
|
this.data = data;
|
||||||
|
this.options = options;
|
||||||
|
};
|
||||||
|
|
||||||
|
ZipObject.prototype = {
|
||||||
|
/**
|
||||||
|
* Return the content as UTF8 string.
|
||||||
|
* @return {string} the UTF8 string.
|
||||||
|
*/
|
||||||
|
asText : function ()
|
||||||
|
{
|
||||||
|
return this.options.binary ? JSZip.prototype.utf8decode(this.data) : this.data;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Returns the binary content.
|
||||||
|
* @return {string} the content as binary.
|
||||||
|
*/
|
||||||
|
asBinary : function ()
|
||||||
|
{
|
||||||
|
return this.options.binary ? this.data : JSZip.prototype.utf8encode(this.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform an integer into a string in hexadecimal.
|
||||||
|
* @private
|
||||||
|
* @param {number} dec the number to convert.
|
||||||
|
* @param {number} bytes the number of bytes to generate.
|
||||||
|
* @returns {string} the result.
|
||||||
|
*/
|
||||||
|
var decToHex = function(dec, bytes) {
|
||||||
|
var hex = "", i;
|
||||||
|
for(i = 0; i < bytes; i++)
|
||||||
|
{
|
||||||
|
hex += String.fromCharCode(dec&0xff);
|
||||||
|
dec=dec>>>8;
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge the objects passed as parameters into a new one.
|
||||||
|
* @private
|
||||||
|
* @param {...Object} var_args All objects to merge.
|
||||||
|
* @return {Object} a new object with the data of the others.
|
||||||
|
*/
|
||||||
|
var extend = function () {
|
||||||
|
var result = {}, i, attr;
|
||||||
|
for (i = 0; i < arguments.length; i++) // arguments is not enumerable in some browsers
|
||||||
|
{
|
||||||
|
for (attr in arguments[i])
|
||||||
|
{
|
||||||
|
if(typeof result[attr] === "undefined")
|
||||||
|
{
|
||||||
|
result[attr] = arguments[i][attr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms the (incomplete) options from the user into the complete
|
||||||
|
* set of options to create a file.
|
||||||
|
* @private
|
||||||
|
* @param {Object} o the options from the user.
|
||||||
|
* @return {Object} the complete set of options.
|
||||||
|
*/
|
||||||
|
var prepareFileAttrs = function (o) {
|
||||||
|
o = o || {};
|
||||||
|
if (o.base64 === true && o.binary == null) {
|
||||||
|
o.binary = true;
|
||||||
|
}
|
||||||
|
o = extend(o, JSZip.defaults);
|
||||||
|
o.date = o.date || new Date();
|
||||||
|
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a file in the current folder.
|
||||||
|
* @private
|
||||||
|
* @param {string} name the name of the file
|
||||||
|
* @param {string} data the data of the file
|
||||||
|
* @param {Object} o the options of the file
|
||||||
|
* @return {Object} the new file.
|
||||||
|
*/
|
||||||
|
var fileAdd = function (name, data, o) {
|
||||||
|
// be sure sub folders exist
|
||||||
|
var parent = parentFolder(name);
|
||||||
|
if (parent) {
|
||||||
|
folderAdd.call(this, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
o = prepareFileAttrs(o);
|
||||||
|
|
||||||
|
return this.files[name] = {name: name, data: data, options:o};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the parent folder of the path.
|
||||||
|
* @private
|
||||||
|
* @param {string} path the path to use
|
||||||
|
* @return {string} the parent folder, or ""
|
||||||
|
*/
|
||||||
|
var parentFolder = function (path) {
|
||||||
|
if (path.slice(-1) == '/')
|
||||||
|
{
|
||||||
|
path = path.substring(0, path.length - 1);
|
||||||
|
}
|
||||||
|
var lastSlash = path.lastIndexOf('/');
|
||||||
|
return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a (sub) folder in the current folder.
|
||||||
|
* @private
|
||||||
|
* @param {string} name the folder's name
|
||||||
|
* @return {Object} the new folder.
|
||||||
|
*/
|
||||||
|
var folderAdd = function (name) {
|
||||||
|
// Check the name ends with a /
|
||||||
|
if (name.slice(-1) != "/") {
|
||||||
|
name += "/"; // IE doesn't like substr(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this folder already exist?
|
||||||
|
if (!this.files[name])
|
||||||
|
{
|
||||||
|
// be sure sub folders exist
|
||||||
|
var parent = parentFolder(name);
|
||||||
|
if (parent) {
|
||||||
|
folderAdd.call(this, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
fileAdd.call(this, name, '', {dir:true});
|
||||||
|
}
|
||||||
|
return this.files[name];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the data found in the local header of a zip file.
|
||||||
|
* Do not create it now, as some parts are re-used later.
|
||||||
|
* @private
|
||||||
|
* @param {Object} file the file to use.
|
||||||
|
* @param {string} utfEncodedFileName the file name, utf8 encoded.
|
||||||
|
* @param {string} compressionType the compression to use.
|
||||||
|
* @return {Object} an object containing header and compressedData.
|
||||||
|
*/
|
||||||
|
var prepareLocalHeaderData = function(file, utfEncodedFileName, compressionType) {
|
||||||
|
var useUTF8 = utfEncodedFileName !== file.name,
|
||||||
|
data = file.data,
|
||||||
|
o = file.options,
|
||||||
|
dosTime,
|
||||||
|
dosDate;
|
||||||
|
|
||||||
|
// date
|
||||||
|
// @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html
|
||||||
|
// @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html
|
||||||
|
// @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html
|
||||||
|
|
||||||
|
dosTime = o.date.getHours();
|
||||||
|
dosTime = dosTime << 6;
|
||||||
|
dosTime = dosTime | o.date.getMinutes();
|
||||||
|
dosTime = dosTime << 5;
|
||||||
|
dosTime = dosTime | o.date.getSeconds() / 2;
|
||||||
|
|
||||||
|
dosDate = o.date.getFullYear() - 1980;
|
||||||
|
dosDate = dosDate << 4;
|
||||||
|
dosDate = dosDate | (o.date.getMonth() + 1);
|
||||||
|
dosDate = dosDate << 5;
|
||||||
|
dosDate = dosDate | o.date.getDate();
|
||||||
|
|
||||||
|
if (o.base64 === true) {
|
||||||
|
data = JSZipBase64.decode(data);
|
||||||
|
}
|
||||||
|
// decode UTF-8 strings if we are dealing with text data
|
||||||
|
if(o.binary === false) {
|
||||||
|
data = this.utf8encode(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var compression = JSZip.compressions[compressionType];
|
||||||
|
var compressedData = compression.compress(data);
|
||||||
|
|
||||||
|
var header = "";
|
||||||
|
|
||||||
|
// version needed to extract
|
||||||
|
header += "\x0A\x00";
|
||||||
|
// general purpose bit flag
|
||||||
|
// set bit 11 if utf8
|
||||||
|
header += useUTF8 ? "\x00\x08" : "\x00\x00";
|
||||||
|
// compression method
|
||||||
|
header += compression.magic;
|
||||||
|
// last mod file time
|
||||||
|
header += decToHex(dosTime, 2);
|
||||||
|
// last mod file date
|
||||||
|
header += decToHex(dosDate, 2);
|
||||||
|
// crc-32
|
||||||
|
header += decToHex(this.crc32(data), 4);
|
||||||
|
// compressed size
|
||||||
|
header += decToHex(compressedData.length, 4);
|
||||||
|
// uncompressed size
|
||||||
|
header += decToHex(data.length, 4);
|
||||||
|
// file name length
|
||||||
|
header += decToHex(utfEncodedFileName.length, 2);
|
||||||
|
// extra field length
|
||||||
|
header += "\x00\x00";
|
||||||
|
|
||||||
|
return {
|
||||||
|
header:header,
|
||||||
|
compressedData:compressedData
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// return the actual prototype of JSZip
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Read an existing zip and merge the data in the current JSZip object.
|
||||||
|
* The implementation is in jszip-load.js, don't forget to include it.
|
||||||
|
* @param {string} stream The stream to load
|
||||||
|
* @param {Object} options Options for loading the stream.
|
||||||
|
* options.base64 : is the stream in base64 ? default : false
|
||||||
|
* @return {JSZip} the current JSZip object
|
||||||
|
*/
|
||||||
|
load : function (stream, options)
|
||||||
|
{
|
||||||
|
throw new Error("Load method is not defined. Is the file jszip-load.js included ?");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter nested files/folders with the specified function.
|
||||||
|
* @param {Function} search the predicate to use :
|
||||||
|
* function (relativePath, file) {...}
|
||||||
|
* It takes 2 arguments : the relative path and the file.
|
||||||
|
* @return {Array} An array of matching elements.
|
||||||
|
*/
|
||||||
|
filter : function (search)
|
||||||
|
{
|
||||||
|
var result = [], filename, relativePath, file, fileClone;
|
||||||
|
for (filename in this.files)
|
||||||
|
{
|
||||||
|
file = this.files[filename];
|
||||||
|
// return a new object, don't let the user mess with our internal objects :)
|
||||||
|
fileClone = new ZipObject(file.name, file.data, extend(file.options));
|
||||||
|
relativePath = filename.slice(this.root.length, filename.length);
|
||||||
|
if (filename.slice(0, this.root.length) === this.root && // the file is in the current root
|
||||||
|
search(relativePath, fileClone)) // and the file matches the function
|
||||||
|
{
|
||||||
|
result.push(fileClone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a file to the zip file, or search a file.
|
||||||
|
* @param {string|RegExp} name The name of the file to add (if data is defined),
|
||||||
|
* the name of the file to find (if no data) or a regex to match files.
|
||||||
|
* @param {string} data The file data, either raw or base64 encoded
|
||||||
|
* @param {Object} o File options
|
||||||
|
* @return {JSZip|Object|Array} this JSZip object (when adding a file),
|
||||||
|
* a file (when searching by string) or an array of files (when searching by regex).
|
||||||
|
*/
|
||||||
|
file : function(name, data, o)
|
||||||
|
{
|
||||||
|
if (arguments.length === 1)
|
||||||
|
{
|
||||||
|
if (name instanceof RegExp)
|
||||||
|
{
|
||||||
|
var regexp = name;
|
||||||
|
return this.filter(function(relativePath, file) {
|
||||||
|
return !file.options.dir && regexp.test(relativePath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else // text
|
||||||
|
{
|
||||||
|
return this.filter(function (relativePath, file) {
|
||||||
|
return !file.options.dir && relativePath === name;
|
||||||
|
})[0]||null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // more than one argument : we have data !
|
||||||
|
{
|
||||||
|
name = this.root+name;
|
||||||
|
fileAdd.call(this, name, data, o);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a directory to the zip file, or search.
|
||||||
|
* @param {String|RegExp} arg The name of the directory to add, or a regex to search folders.
|
||||||
|
* @return {JSZip} an object with the new directory as the root, or an array containing matching folders.
|
||||||
|
*/
|
||||||
|
folder : function(arg)
|
||||||
|
{
|
||||||
|
if (!arg)
|
||||||
|
{
|
||||||
|
throw new Error("folder : wrong argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg instanceof RegExp)
|
||||||
|
{
|
||||||
|
return this.filter(function(relativePath, file) {
|
||||||
|
return file.options.dir && arg.test(relativePath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// else, name is a new folder
|
||||||
|
var name = this.root + arg;
|
||||||
|
var newFolder = folderAdd.call(this, name);
|
||||||
|
|
||||||
|
// Allow chaining by returning a new object with this folder as the root
|
||||||
|
var ret = this.clone();
|
||||||
|
ret.root = newFolder.name;
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a file, or a directory and all sub-files, from the zip
|
||||||
|
* @param {string} name the name of the file to delete
|
||||||
|
* @return {JSZip} this JSZip object
|
||||||
|
*/
|
||||||
|
remove : function(name)
|
||||||
|
{
|
||||||
|
name = this.root + name;
|
||||||
|
var file = this.files[name];
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
// Look for any folders
|
||||||
|
if (name.slice(-1) != "/") {
|
||||||
|
name += "/";
|
||||||
|
}
|
||||||
|
file = this.files[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
if (!file.options.dir)
|
||||||
|
{
|
||||||
|
// file
|
||||||
|
delete this.files[name];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// folder
|
||||||
|
var kids = this.filter(function (relativePath, file) {
|
||||||
|
return file.name.slice(0, name.length) === name;
|
||||||
|
});
|
||||||
|
for (var i = 0; i < kids.length; i++)
|
||||||
|
{
|
||||||
|
delete this.files[kids[i].name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the complete zip file
|
||||||
|
* @param {Object} options the options to generate the zip file :
|
||||||
|
* - base64, true to generate base64.
|
||||||
|
* - compression, "STORE" by default.
|
||||||
|
* @return {string} the zip file
|
||||||
|
*/
|
||||||
|
generate : function(options)
|
||||||
|
{
|
||||||
|
options = extend(options || {}, {
|
||||||
|
base64 : true,
|
||||||
|
compression : "STORE"
|
||||||
|
});
|
||||||
|
var compression = options.compression.toUpperCase();
|
||||||
|
|
||||||
|
// The central directory, and files data
|
||||||
|
var directory = [], files = [], fileOffset = 0;
|
||||||
|
|
||||||
|
if (!JSZip.compressions[compression]) {
|
||||||
|
throw compression + " is not a valid compression method !";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var name in this.files)
|
||||||
|
{
|
||||||
|
if( !this.files.hasOwnProperty(name) ) { continue; }
|
||||||
|
|
||||||
|
var file = this.files[name];
|
||||||
|
|
||||||
|
var utfEncodedFileName = this.utf8encode(file.name);
|
||||||
|
|
||||||
|
var fileRecord = "",
|
||||||
|
dirRecord = "",
|
||||||
|
data = prepareLocalHeaderData.call(this, file, utfEncodedFileName, compression);
|
||||||
|
fileRecord = JSZip.signature.LOCAL_FILE_HEADER + data.header + utfEncodedFileName + data.compressedData;
|
||||||
|
|
||||||
|
dirRecord = JSZip.signature.CENTRAL_FILE_HEADER +
|
||||||
|
// version made by (00: DOS)
|
||||||
|
"\x14\x00" +
|
||||||
|
// file header (common to file and central directory)
|
||||||
|
data.header +
|
||||||
|
// file comment length
|
||||||
|
"\x00\x00" +
|
||||||
|
// disk number start
|
||||||
|
"\x00\x00" +
|
||||||
|
// internal file attributes TODO
|
||||||
|
"\x00\x00" +
|
||||||
|
// external file attributes
|
||||||
|
(this.files[name].dir===true?"\x10\x00\x00\x00":"\x00\x00\x00\x00")+
|
||||||
|
// relative offset of local header
|
||||||
|
decToHex(fileOffset, 4) +
|
||||||
|
// file name
|
||||||
|
utfEncodedFileName;
|
||||||
|
|
||||||
|
fileOffset += fileRecord.length;
|
||||||
|
|
||||||
|
files.push(fileRecord);
|
||||||
|
directory.push(dirRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileData = files.join("");
|
||||||
|
var dirData = directory.join("");
|
||||||
|
|
||||||
|
var dirEnd = "";
|
||||||
|
|
||||||
|
// end of central dir signature
|
||||||
|
dirEnd = JSZip.signature.CENTRAL_DIRECTORY_END +
|
||||||
|
// number of this disk
|
||||||
|
"\x00\x00" +
|
||||||
|
// number of the disk with the start of the central directory
|
||||||
|
"\x00\x00" +
|
||||||
|
// total number of entries in the central directory on this disk
|
||||||
|
decToHex(files.length, 2) +
|
||||||
|
// total number of entries in the central directory
|
||||||
|
decToHex(files.length, 2) +
|
||||||
|
// size of the central directory 4 bytes
|
||||||
|
decToHex(dirData.length, 4) +
|
||||||
|
// offset of start of central directory with respect to the starting disk number
|
||||||
|
decToHex(fileData.length, 4) +
|
||||||
|
// .ZIP file comment length
|
||||||
|
"\x00\x00";
|
||||||
|
|
||||||
|
var zip = fileData + dirData + dirEnd;
|
||||||
|
return (options.base64) ? JSZipBase64.encode(zip) : zip;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Javascript crc32
|
||||||
|
* http://www.webtoolkit.info/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
crc32 : function(str, crc)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (str === "" || typeof str === "undefined") {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D";
|
||||||
|
|
||||||
|
if (typeof(crc) == "undefined") { crc = 0; }
|
||||||
|
var x = 0;
|
||||||
|
var y = 0;
|
||||||
|
|
||||||
|
crc = crc ^ (-1);
|
||||||
|
for( var i = 0, iTop = str.length; i < iTop; i++ ) {
|
||||||
|
y = ( crc ^ str.charCodeAt( i ) ) & 0xFF;
|
||||||
|
x = "0x" + table.substr( y * 9, 8 );
|
||||||
|
crc = ( crc >>> 8 ) ^ x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc ^ (-1);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// Inspired by http://my.opera.com/GreyWyvern/blog/show.dml/1725165
|
||||||
|
clone : function()
|
||||||
|
{
|
||||||
|
var newObj = new JSZip();
|
||||||
|
for (var i in this)
|
||||||
|
{
|
||||||
|
if (typeof this[i] !== "function")
|
||||||
|
{
|
||||||
|
newObj[i] = this[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newObj;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://www.webtoolkit.info/javascript-utf8.html
|
||||||
|
*/
|
||||||
|
utf8encode : function (string) {
|
||||||
|
string = string.replace(/\r\n/g,"\n");
|
||||||
|
var utftext = "";
|
||||||
|
|
||||||
|
for (var n = 0; n < string.length; n++) {
|
||||||
|
|
||||||
|
var c = string.charCodeAt(n);
|
||||||
|
|
||||||
|
if (c < 128) {
|
||||||
|
utftext += String.fromCharCode(c);
|
||||||
|
}
|
||||||
|
else if((c > 127) && (c < 2048)) {
|
||||||
|
utftext += String.fromCharCode((c >> 6) | 192);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utftext += String.fromCharCode((c >> 12) | 224);
|
||||||
|
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return utftext;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://www.webtoolkit.info/javascript-utf8.html
|
||||||
|
*/
|
||||||
|
utf8decode : function (utftext) {
|
||||||
|
var string = "";
|
||||||
|
var i = 0;
|
||||||
|
var c = 0, c1 = 0, c2 = 0, c3 = 0;
|
||||||
|
|
||||||
|
while ( i < utftext.length ) {
|
||||||
|
|
||||||
|
c = utftext.charCodeAt(i);
|
||||||
|
|
||||||
|
if (c < 128) {
|
||||||
|
string += String.fromCharCode(c);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if((c > 191) && (c < 224)) {
|
||||||
|
c2 = utftext.charCodeAt(i+1);
|
||||||
|
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c2 = utftext.charCodeAt(i+1);
|
||||||
|
c3 = utftext.charCodeAt(i+2);
|
||||||
|
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compression methods
|
||||||
|
* This object is filled in as follow :
|
||||||
|
* name : {
|
||||||
|
* magic // the 2 bytes indentifying the compression method
|
||||||
|
* compress // function, take the uncompressed content and return it compressed.
|
||||||
|
* uncompress // function, take the compressed content and return it uncompressed.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* STORE is the default compression method, so it's included in this file.
|
||||||
|
* Other methods should go to separated files : the user wants modularity.
|
||||||
|
*/
|
||||||
|
JSZip.compressions = {
|
||||||
|
"STORE" : {
|
||||||
|
magic : "\x00\x00",
|
||||||
|
compress : function (content)
|
||||||
|
{
|
||||||
|
return content; // no compression
|
||||||
|
},
|
||||||
|
uncompress : function (content)
|
||||||
|
{
|
||||||
|
return content; // no compression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Base64 encode / decode
|
||||||
|
* http://www.webtoolkit.info/
|
||||||
|
*
|
||||||
|
* Hacked so that it doesn't utf8 en/decode everything
|
||||||
|
**/
|
||||||
|
var JSZipBase64 = (function() {
|
||||||
|
// private property
|
||||||
|
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||||
|
|
||||||
|
return {
|
||||||
|
// public method for encoding
|
||||||
|
encode : function(input, utf8) {
|
||||||
|
var output = "";
|
||||||
|
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
while (i < input.length) {
|
||||||
|
|
||||||
|
chr1 = input.charCodeAt(i++);
|
||||||
|
chr2 = input.charCodeAt(i++);
|
||||||
|
chr3 = input.charCodeAt(i++);
|
||||||
|
|
||||||
|
enc1 = chr1 >> 2;
|
||||||
|
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||||
|
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||||
|
enc4 = chr3 & 63;
|
||||||
|
|
||||||
|
if (isNaN(chr2)) {
|
||||||
|
enc3 = enc4 = 64;
|
||||||
|
} else if (isNaN(chr3)) {
|
||||||
|
enc4 = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = output +
|
||||||
|
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
|
||||||
|
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
// public method for decoding
|
||||||
|
decode : function(input, utf8) {
|
||||||
|
var output = "";
|
||||||
|
var chr1, chr2, chr3;
|
||||||
|
var enc1, enc2, enc3, enc4;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||||
|
|
||||||
|
while (i < input.length) {
|
||||||
|
|
||||||
|
enc1 = _keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc2 = _keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc3 = _keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc4 = _keyStr.indexOf(input.charAt(i++));
|
||||||
|
|
||||||
|
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||||
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||||
|
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||||
|
|
||||||
|
output = output + String.fromCharCode(chr1);
|
||||||
|
|
||||||
|
if (enc3 != 64) {
|
||||||
|
output = output + String.fromCharCode(chr2);
|
||||||
|
}
|
||||||
|
if (enc4 != 64) {
|
||||||
|
output = output + String.fromCharCode(chr3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
// enforcing Stuk's coding style
|
||||||
|
// vim: set shiftwidth=3 softtabstop=3:
|
|
@ -0,0 +1,258 @@
|
||||||
|
/* Author: Artem Sapegin, http://sapegin.me, 2012 */
|
||||||
|
|
||||||
|
/*global tamia:false, doT:true, htmlhl:false, JSZip:false, store:false */
|
||||||
|
;(function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$.extend(doT.templateSettings, {
|
||||||
|
strip: false,
|
||||||
|
varname: '$'
|
||||||
|
});
|
||||||
|
|
||||||
|
var lang = $('html').attr('lang'),
|
||||||
|
skins = ['flat', 'classic', 'birman'],
|
||||||
|
skin = 'classic',
|
||||||
|
downloadData = {
|
||||||
|
lang: lang,
|
||||||
|
jquery_ver: jQuery.fn.jquery,
|
||||||
|
footer: $('#index_footer_tmpl').html(),
|
||||||
|
html: '',
|
||||||
|
skin: skin
|
||||||
|
},
|
||||||
|
prefix = location.hostname === '127.0.0.1' ? '' : '/social-likes/',
|
||||||
|
sourceFiles = {
|
||||||
|
'social-likes.min.js': {url: prefix + 'src/social-likes.min.js'},
|
||||||
|
'social-likes_{skin}.css': {url: prefix + 'src/social-likes_{skin}.css'}
|
||||||
|
},
|
||||||
|
templateIndex = doT.template($('#index_tmpl').html().replace(/\\\//g, '/')),
|
||||||
|
experimental = location.hash === '#ponies',
|
||||||
|
// simple = !('download' in document.createElement('a'));
|
||||||
|
simple = true; // Because of bug in Chrome 35: https://code.google.com/p/chromium/issues/detail?id=377860
|
||||||
|
|
||||||
|
// stackoverflow.com/questions/1184624/convert-form-data-to-js-object-with-jquery
|
||||||
|
$.fn.serializeObject = function() {
|
||||||
|
var o = {};
|
||||||
|
var a = this.serializeArray();
|
||||||
|
$.each(a, function() {
|
||||||
|
if (o[this.name] !== undefined) {
|
||||||
|
if (!o[this.name].push) {
|
||||||
|
o[this.name] = [o[this.name]];
|
||||||
|
}
|
||||||
|
o[this.name].push(this.value || '');
|
||||||
|
} else {
|
||||||
|
o[this.name] = this.value || '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// jasonwyatt.tumblr.com/post/10481498815/how-to-correctly-debounce-a-javascript-function
|
||||||
|
function debounce(fn, debounceDuration){
|
||||||
|
// summary:
|
||||||
|
// Returns a debounced function that will make sure the given
|
||||||
|
// function is not triggered too much.
|
||||||
|
// fn: Function
|
||||||
|
// Function to debounce.
|
||||||
|
// debounceDuration: Number
|
||||||
|
// OPTIONAL. The amount of time in milliseconds for which we
|
||||||
|
// will debounce the function. (defaults to 100ms)
|
||||||
|
|
||||||
|
debounceDuration = debounceDuration || 100;
|
||||||
|
|
||||||
|
return function(){
|
||||||
|
if (!fn.debouncing) {
|
||||||
|
fn.debouncing = true;
|
||||||
|
}
|
||||||
|
clearTimeout(fn.debounceTimeout);
|
||||||
|
var args = Array.prototype.slice.apply(arguments);
|
||||||
|
fn.debounceTimeout = setTimeout(function() {
|
||||||
|
fn.lastReturnVal = fn.apply(window, args);
|
||||||
|
fn.debouncing = false;
|
||||||
|
}, debounceDuration);
|
||||||
|
|
||||||
|
return fn.lastReturnVal;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeValue(value) {
|
||||||
|
return value
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeFormData(data) {
|
||||||
|
var fields = ['url', 'title', 'twitter_via', 'twitter_related', 'pinterest_media'];
|
||||||
|
for (var fieldIdx = 0; fieldIdx < fields.length; fieldIdx++) {
|
||||||
|
var field = fields[fieldIdx];
|
||||||
|
data[field] = escapeValue(data[field]);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillForm(form, data) {
|
||||||
|
jQuery.each(data, function(name, value) {
|
||||||
|
var field = form.find('[name="' + name + '"]'),
|
||||||
|
type = field.attr('type');
|
||||||
|
switch (type) {
|
||||||
|
case 'checkbox':
|
||||||
|
field.prop('checked', !!value);
|
||||||
|
break;
|
||||||
|
case 'radio':
|
||||||
|
field.filter('[value="' + value + '"]').prop('checked', true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
field.val(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanHtml(code) {
|
||||||
|
return code
|
||||||
|
.replace(/\n[\n\t]*\n/g, '\n') // Remove empty lines
|
||||||
|
.replace(/ {2,}/g, ' ') // Remove extra spaces
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlight(code) {
|
||||||
|
return htmlhl(code.replace(/\\\//g, '/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function download(e) {
|
||||||
|
var files = getFiles();
|
||||||
|
|
||||||
|
var zip = new JSZip();
|
||||||
|
zip.file('index.html', templateIndex(downloadData));
|
||||||
|
|
||||||
|
for (var fileName in files) {
|
||||||
|
zip.file(fileName, files[fileName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = zip.generate();
|
||||||
|
|
||||||
|
if (simple) {
|
||||||
|
var form = $('#download-proxy'),
|
||||||
|
field = form.find('[name="content"]');
|
||||||
|
field.val(content);
|
||||||
|
form.submit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(e.target).attr('href', 'data:application/zip;base64,' + content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFiles() {
|
||||||
|
var files = {};
|
||||||
|
for (var fileName in sourceFiles) {
|
||||||
|
files[getFilenameForSkin(fileName)] = getFile(fileName);
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFile(fileName) {
|
||||||
|
var file = sourceFiles[fileName];
|
||||||
|
var url = getFilenameForSkin(file.url);
|
||||||
|
if (!file.files) file.files = {};
|
||||||
|
if (!file.files[url]) {
|
||||||
|
$.ajax(url, { async: false, dataType: 'html' }).then(function(data) {
|
||||||
|
file.files[url] = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return file.files[url];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFilenameForSkin(fileName) {
|
||||||
|
return fileName.replace('{skin}', skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
tamia.initComponents({
|
||||||
|
builder: function(elem) {
|
||||||
|
var form = $(elem),
|
||||||
|
preview = $('.js-preview'),
|
||||||
|
code = $('.js-code'),
|
||||||
|
twitterExtra = form.find('.js-twitter-extra'),
|
||||||
|
pinterestExtra = form.find('.js-pinterest-extra'),
|
||||||
|
lightStyle = form.find('.js-light'),
|
||||||
|
prepend = doT.template($('#prepend_tmpl').html()),
|
||||||
|
template = doT.template($('#build_tmpl').html()),
|
||||||
|
previous;
|
||||||
|
|
||||||
|
var delayedUpdate = debounce(function(html, data) {
|
||||||
|
// Switch skin
|
||||||
|
skin = data.skin;
|
||||||
|
|
||||||
|
$.each(skins, function(i, s) {
|
||||||
|
$('#styles_' + s).prop('disabled', s !== skin);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Render preview
|
||||||
|
preview.attr('class', preview.attr('class').replace(/(preview_)\w+/, '$1' + data.type));
|
||||||
|
preview.html(html);
|
||||||
|
preview.find('.social-likes').socialLikes();
|
||||||
|
|
||||||
|
form.find('.js-experimental').toggleClass('is-hidden', !experimental);
|
||||||
|
|
||||||
|
store.set(lang, {
|
||||||
|
skin: skin,
|
||||||
|
type: data.type,
|
||||||
|
counters: !!data.counters,
|
||||||
|
light: !!data.light,
|
||||||
|
title: data.title,
|
||||||
|
url: data.url,
|
||||||
|
site_facebook: !!data.site_facebook,
|
||||||
|
site_mailru: !!data.site_mailru,
|
||||||
|
site_odnoklassniki: !!data.site_odnoklassniki,
|
||||||
|
site_plusone: !!data.site_plusone,
|
||||||
|
site_twitter: !!data.site_twitter,
|
||||||
|
site_pinterest: !!data.site_pinterest,
|
||||||
|
site_vkontakte: !!data.site_vkontakte,
|
||||||
|
twitter_related: data.twitter_related,
|
||||||
|
twitter_via: data.twitter_via,
|
||||||
|
pinterest_media: data.pinterest_media
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var loadOptions = function() {
|
||||||
|
var data = store.get(lang);
|
||||||
|
if (data) fillForm(form, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var dataString = form.serialize();
|
||||||
|
if (dataString !== previous) {
|
||||||
|
var data = escapeFormData(form.serializeObject());
|
||||||
|
data.experimental = experimental;
|
||||||
|
|
||||||
|
twitterExtra.toggleClass('is-hidden', data.site_twitter !== '1');
|
||||||
|
pinterestExtra.toggleClass('is-hidden', data.site_pinterest !== '1');
|
||||||
|
lightStyle.toggleClass('is-hidden', data.skin !== 'flat');
|
||||||
|
|
||||||
|
var html = cleanHtml(template(data));
|
||||||
|
code.html(highlight(prepend(data) + html));
|
||||||
|
delayedUpdate(html, data);
|
||||||
|
downloadData.html = html;
|
||||||
|
downloadData.skin = data.skin;
|
||||||
|
|
||||||
|
previous = dataString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadOptions();
|
||||||
|
|
||||||
|
form.on('change input', 'input', update);
|
||||||
|
update();
|
||||||
|
|
||||||
|
form.submit(function() {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.js-download').click(download);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}(jQuery));
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* Author: Artem Sapegin, http://sapegin.me, 2012 */
|
||||||
|
|
||||||
|
/*jshint browser:true, jquery:true, white:false, smarttabs:true, eqeqeq:true,
|
||||||
|
immed:true, latedef:true, newcap:true, undef:true */
|
||||||
|
/*global jQuery:false, define:false*/
|
||||||
|
(function (factory) { // Try to register as an anonymous AMD module
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define([], factory);
|
||||||
|
} else {
|
||||||
|
factory();
|
||||||
|
}
|
||||||
|
}(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var regexps = [
|
||||||
|
[/<(\/?)([\w]+)([^>]*)>/g, '←<$1→←tag:$2→$3←>→'], // Tag
|
||||||
|
[/ ([\-\w]+)/g, ' ←attr:$1→'] // Attribute
|
||||||
|
],
|
||||||
|
saveStringsRe = [
|
||||||
|
/"([^"]+)"/mg
|
||||||
|
],
|
||||||
|
restoreStringsRe = /↑(\d+)↓/g,
|
||||||
|
savedStrings,
|
||||||
|
savedStringsNum;
|
||||||
|
|
||||||
|
function save_strings(code) {
|
||||||
|
function save(s) {
|
||||||
|
savedStrings[savedStringsNum] = s;
|
||||||
|
return '↑' + savedStringsNum++ + '↓';
|
||||||
|
}
|
||||||
|
|
||||||
|
savedStringsNum = 0;
|
||||||
|
savedStrings = [];
|
||||||
|
for (var reIdx = 0; reIdx < saveStringsRe.length; reIdx++) {
|
||||||
|
code = code.replace(saveStringsRe[reIdx], save);
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
function restore_strings(code) {
|
||||||
|
code = code.replace(restoreStringsRe, function(s, num) {
|
||||||
|
return savedStrings[num];
|
||||||
|
});
|
||||||
|
savedStringsNum = 0;
|
||||||
|
savedStrings = [];
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlight(code) {
|
||||||
|
code = save_strings(code);
|
||||||
|
for (var regexpIdx = 0; regexpIdx < regexps.length; regexpIdx++) {
|
||||||
|
var re = regexps[regexpIdx];
|
||||||
|
code = code.replace(re[0], re[1]);
|
||||||
|
}
|
||||||
|
code = restore_strings(code);
|
||||||
|
code = code.replace(/\=("[^\"]*")/g, '←=→←str:$1→'); // Attribute values
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
function htmlize(code) {
|
||||||
|
return code
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/←([^:→]+)→/g, '←gray:$1→')
|
||||||
|
.replace(/←(\w+):([^→]+)→/g, '<span class="hl-$1">$2</span>')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (window.htmlhl = function(code) {
|
||||||
|
return htmlize(highlight(code));
|
||||||
|
});
|
||||||
|
}));
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
try {
|
||||||
|
$content = base64_decode($_POST['content']);
|
||||||
|
if (empty($content)) throw new Exception();
|
||||||
|
header('Content-type: application/zip');
|
||||||
|
header('Content-Disposition: attachment; filename="social-likes.zip"');
|
||||||
|
echo $content;
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
header('HTTP/1.0 400 Bad request');
|
||||||
|
echo 'Bad request.';
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -0,0 +1,166 @@
|
||||||
|
/* Author: Artem Sapegin, http://sapegin.me, 2012 */
|
||||||
|
|
||||||
|
link-color = #cf6c0a;
|
||||||
|
visited-color = #7c579e;
|
||||||
|
hover-color = #ff6900;
|
||||||
|
noise = url('../img/noise.png');
|
||||||
|
|
||||||
|
body {
|
||||||
|
background:#fff;
|
||||||
|
color:#111;
|
||||||
|
font-size:18px;
|
||||||
|
line-height:1.4;
|
||||||
|
min-width:1024px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
position:relative;
|
||||||
|
max-width:1100px;
|
||||||
|
margin:0 auto;
|
||||||
|
padding:2*spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
* { font-family:"Helvetica Neue", Tahoma, sans-serif; }
|
||||||
|
pre, code, pre span { font-family:Consolas, "Lucida Console", Monaco, "Courier New", Courier, monospace; }
|
||||||
|
|
||||||
|
|
||||||
|
// Links
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration:underline;
|
||||||
|
transition:border .1s ease-in-out, color .2s ease-in-out, background .2s ease-in-out;
|
||||||
|
}
|
||||||
|
a.fake {
|
||||||
|
text-decoration:none;
|
||||||
|
border-bottom:1px dotted;
|
||||||
|
}
|
||||||
|
a:link, nav a:visited, a.fake:visited {
|
||||||
|
color:link-color;
|
||||||
|
}
|
||||||
|
a:visited {
|
||||||
|
color:visited-color;
|
||||||
|
}
|
||||||
|
a:hover, a:active, a:focus, nav a:hover, nav a:active, nav a:focus, a.fake:hover, a.fake:active, a.fake:focus {
|
||||||
|
color:hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Text selection
|
||||||
|
text-selection(#000, #faedb1);
|
||||||
|
|
||||||
|
// iOS tap highlighting: j.mp/webkit-tap-highlight-color
|
||||||
|
a:link {
|
||||||
|
-webkit-tap-highlight-color:#ff5e99;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Page elements
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size:64px;
|
||||||
|
margin:0 0 16px;
|
||||||
|
line-height:1;
|
||||||
|
font-weight:normal;
|
||||||
|
letter-spacing:-.2px;
|
||||||
|
}
|
||||||
|
h2, h3 {
|
||||||
|
line-height:40px;
|
||||||
|
margin:16px 0 0;
|
||||||
|
font-weight:normal;
|
||||||
|
letter-spacing:-.2px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size:24px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size:22px;
|
||||||
|
font-style:italic;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Code
|
||||||
|
|
||||||
|
.code {
|
||||||
|
display: block
|
||||||
|
white-space: pre-wrap
|
||||||
|
-moz-tab-size: 4
|
||||||
|
-o-tab-size: 4
|
||||||
|
tab-size: 4
|
||||||
|
|
||||||
|
code {
|
||||||
|
display: block
|
||||||
|
font-size: 15px
|
||||||
|
line-height: 1.3
|
||||||
|
}
|
||||||
|
|
||||||
|
.indent {
|
||||||
|
display: inline-block
|
||||||
|
width: 2.2em
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pre code::-webkit-scrollbar {
|
||||||
|
width:9px;
|
||||||
|
height:9px;
|
||||||
|
}
|
||||||
|
pre code::-webkit-scrollbar-track-piece {
|
||||||
|
background:white(.2);
|
||||||
|
}
|
||||||
|
pre code::-webkit-scrollbar-thumb {
|
||||||
|
background:white(.6);
|
||||||
|
border-radius:8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitHub page elements
|
||||||
|
|
||||||
|
.forkme {
|
||||||
|
position:fixed;
|
||||||
|
top:0;
|
||||||
|
right:0;
|
||||||
|
width:149px;
|
||||||
|
height:149px;
|
||||||
|
z-index:999;
|
||||||
|
|
||||||
|
&-i {
|
||||||
|
+link-all-states() {
|
||||||
|
color:#fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
position:relative;
|
||||||
|
right:-37px;
|
||||||
|
top:-22px;
|
||||||
|
display:block;
|
||||||
|
width:190px;
|
||||||
|
padding:5px 15px;
|
||||||
|
text-align:center;
|
||||||
|
font-size:14px;
|
||||||
|
background:#f9970d;
|
||||||
|
text-decoration:none;
|
||||||
|
text-shadow:0 -1px 0 black(.15);
|
||||||
|
transform-origin:0 0;
|
||||||
|
transform:rotate(45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width:1150px) {
|
||||||
|
.forkme {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.download {
|
||||||
|
float:right;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
font-size:19px;
|
||||||
|
margin:5px 0 1em 0;
|
||||||
|
font-style:italic;
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
padding:spacer;
|
||||||
|
text-align:center;
|
||||||
|
font-size:14px;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
/* Author: Artem Sapegin, http://sapegin.me, 2013 */
|
||||||
|
|
||||||
|
sticky_footer_height = 40px;
|
||||||
|
form_focus_color = #f59300;
|
||||||
|
|
||||||
|
@import "tamia";
|
||||||
|
@import "modules/form";
|
||||||
|
@import "modules/checkbox";
|
||||||
|
@import "modules/switcher";
|
||||||
|
@import "gh-page";
|
||||||
|
@import "styles";
|
|
@ -0,0 +1,144 @@
|
||||||
|
// Author: Artem Sapegin, http://sapegin.me, 2013
|
||||||
|
|
||||||
|
.language-switcher {
|
||||||
|
position:absolute;
|
||||||
|
top:15px;
|
||||||
|
right:2*spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
space(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forms
|
||||||
|
.builder {
|
||||||
|
space(3);
|
||||||
|
|
||||||
|
&__row {
|
||||||
|
clearfix();
|
||||||
|
margin-top:.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
float:left;
|
||||||
|
width:15%;
|
||||||
|
line-height:28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__widget {
|
||||||
|
float:right;
|
||||||
|
width:85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__checkbox {
|
||||||
|
float:left;
|
||||||
|
width:20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-half &__label {
|
||||||
|
width:30.67%;
|
||||||
|
}
|
||||||
|
.l-half &__widget {
|
||||||
|
width:69.33%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox__input:checked + .checkbox__label .checkbox__button,
|
||||||
|
.radio__input:checked + .radio__label .radio__button,
|
||||||
|
.checkbox__input:not(:checked) + .checkbox__label .checkbox__button,
|
||||||
|
.radio__input:not(:checked) + .radio__label .radio__button {
|
||||||
|
margin-top:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
space(2);
|
||||||
|
min-height:150px;
|
||||||
|
padding:6*spacer 0 0;
|
||||||
|
text-align:center;
|
||||||
|
|
||||||
|
&_vertical {
|
||||||
|
padding-top:0;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
space(4);
|
||||||
|
padding:spacer;
|
||||||
|
background:#f5f2f0;
|
||||||
|
border-radius:3px
|
||||||
|
border:1px solid #ccc
|
||||||
|
border-color:black(.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Syntax highlighting
|
||||||
|
.hl-gray {
|
||||||
|
color:#999;
|
||||||
|
}
|
||||||
|
.hl-tag {
|
||||||
|
color:#905;
|
||||||
|
}
|
||||||
|
.hl-attr {
|
||||||
|
color:#690;
|
||||||
|
}
|
||||||
|
.hl-str {
|
||||||
|
color:#07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Download row
|
||||||
|
.download-row {
|
||||||
|
margin-bottom:2*spacer;
|
||||||
|
|
||||||
|
&__links {
|
||||||
|
margin-bottom:1.5*spacer;
|
||||||
|
.big-button {
|
||||||
|
margin-right:.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__button {
|
||||||
|
display:inline-block;
|
||||||
|
font-size:36px;
|
||||||
|
// position:relative;
|
||||||
|
}
|
||||||
|
&__descr {
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.docs {
|
||||||
|
margin-bottom:spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download button
|
||||||
|
.big-button,
|
||||||
|
.big-button:link,
|
||||||
|
.big-button:visited {
|
||||||
|
tweak-inverted-text();
|
||||||
|
display:inline-block;
|
||||||
|
padding:10px 20px;
|
||||||
|
background:#ff6d00;
|
||||||
|
background:linear-gradient(to bottom, #ffb300, #ff6d00);
|
||||||
|
border-radius:5px;
|
||||||
|
color:#fff;
|
||||||
|
font-size:36px;
|
||||||
|
text-decoration:none;
|
||||||
|
text-shadow:0 -1px 0 black(.15);
|
||||||
|
outline:0;
|
||||||
|
}
|
||||||
|
.big-button:hover,
|
||||||
|
.big-button:focus {
|
||||||
|
background:#ff7c1a;
|
||||||
|
background:linear-gradient(to bottom, #fbbd00, #ff750d);
|
||||||
|
}
|
||||||
|
.big-button:active {
|
||||||
|
position:relative;
|
||||||
|
top:1px;
|
||||||
|
margin-top:-1px;
|
||||||
|
margin-bottom:1px;
|
||||||
|
padding:11px 20px 9px;
|
||||||
|
background:#faa643;
|
||||||
|
background:linear-gradient(to bottom, #ff7c1a, #faa643);
|
||||||
|
box-shadow:inset 0 2px 2px black(.2);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Checkbox and radio button
|
||||||
|
|
||||||
|
Checkbox and radio button with custom design.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
Checkbox:
|
||||||
|
|
||||||
|
<div class="checkbox">
|
||||||
|
<input class="checkbox__input" id="my_checkbox" type="checkbox" name="my_checkbox" value="yes" checked="checked">
|
||||||
|
<label class="checkbox__label" for="my_checkbox">
|
||||||
|
<span class="checkbox__button"></span>
|
||||||
|
<span class="checkbox__text">My checkbox</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Radio button:
|
||||||
|
|
||||||
|
<div class="radiobutton">
|
||||||
|
<input class="radiobutton__input" id="my_radio" type="checkbox" name="my_radio" value="dog" checked="checked">
|
||||||
|
<label class="radiobutton__label" for="my_radio">
|
||||||
|
<span class="radiobutton__button"></span>
|
||||||
|
<span class="radiobutton__text">My radio button</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Skin
|
||||||
|
|
||||||
|
Set `checkbox_default_skin` or `modules_default_skin` to `true` to enable default skin.
|
|
@ -0,0 +1 @@
|
||||||
|
<svg width="12" height="11" xmlns="http://www.w3.org/2000/svg"><path d="M0 5.899l2.136-2.432 2.342 2.668 5.387-6.135 2.136 2.432-7.522 8.568-4.478-5.101zm0 0" fill="#444"/></svg>
|
After Width: | Height: | Size: 179 B |
|
@ -0,0 +1,43 @@
|
||||||
|
<div class="checkbox">
|
||||||
|
<input class="checkbox__input" id="check1" type="checkbox" name="check" value="yes" checked>
|
||||||
|
<label class="checkbox__label" for="check1">
|
||||||
|
<span class="checkbox__button"></span>
|
||||||
|
<span class="checkbox__text fixie"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox">
|
||||||
|
<input class="checkbox__input" id="check2" type="checkbox" name="check2" value="yes">
|
||||||
|
<label class="checkbox__label" for="check2">
|
||||||
|
<span class="checkbox__button"></span>
|
||||||
|
<span class="checkbox__text fixie"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox is-disabled">
|
||||||
|
<input class="checkbox__input" id="check3" type="checkbox" name="check3" value="yes" checked disabled>
|
||||||
|
<label class="checkbox__label" for="check3">
|
||||||
|
<span class="checkbox__button"></span>
|
||||||
|
<span class="checkbox__text fixie"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="radio">
|
||||||
|
<input class="radio__input" id="radio1" type="radio" name="radio" value="dog" checked>
|
||||||
|
<label class="radio__label" for="radio1">
|
||||||
|
<span class="radio__button"></span>
|
||||||
|
<span class="radio__text fixie"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="radio">
|
||||||
|
<input class="radio__input" id="radio2" type="radio" name="radio" value="hamster">
|
||||||
|
<label class="radio__label" for="radio2">
|
||||||
|
<span class="radio__button"></span>
|
||||||
|
<span class="radio__text fixie"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="radio is-disabled">
|
||||||
|
<input class="radio__input" id="radio3" type="radio" name="radio" value="cat" disabled>
|
||||||
|
<label class="radio__label" for="radio3">
|
||||||
|
<span class="radio__button"></span>
|
||||||
|
<span class="radio__text fixie"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
|
@ -0,0 +1,108 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Checkbox and radio button
|
||||||
|
// Requires Modernizr.svg
|
||||||
|
// Dependencies: form
|
||||||
|
|
||||||
|
// Bones
|
||||||
|
|
||||||
|
.checkbox,
|
||||||
|
.radio
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
|
&__button
|
||||||
|
// For prehistoric browsers
|
||||||
|
display: none
|
||||||
|
|
||||||
|
&__text
|
||||||
|
display: inline-block
|
||||||
|
white-space: normal
|
||||||
|
|
||||||
|
&__button,
|
||||||
|
&__text
|
||||||
|
vertical-align: middle
|
||||||
|
|
||||||
|
|
||||||
|
&__input:checked,
|
||||||
|
&__input:not(:checked)
|
||||||
|
// Input should be hidden but focusable
|
||||||
|
// display:none and width=height=0 don’t work here
|
||||||
|
position: absolute
|
||||||
|
opacity: 0
|
||||||
|
overflow: hidden
|
||||||
|
height: 1px
|
||||||
|
width: 1px
|
||||||
|
padding: 0
|
||||||
|
border: 0
|
||||||
|
|
||||||
|
&__input:checked + &__label &__button,
|
||||||
|
&__input:not(:checked) + &__label &__button
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
&__input:checked + &__label &__button
|
||||||
|
position: relative
|
||||||
|
&:before
|
||||||
|
content: ""
|
||||||
|
position: absolute
|
||||||
|
line-height: 1
|
||||||
|
|
||||||
|
&.is-disabled &__input + &__label
|
||||||
|
opacity: .4
|
||||||
|
|
||||||
|
|
||||||
|
// Default skin
|
||||||
|
|
||||||
|
modules_default_skin ?= true
|
||||||
|
checkbox_default_skin ?= false
|
||||||
|
|
||||||
|
if modules_default_skin or checkbox_default_skin
|
||||||
|
|
||||||
|
.checkbox,
|
||||||
|
.radio
|
||||||
|
&__button,
|
||||||
|
&__text
|
||||||
|
line-height: 1.8
|
||||||
|
font-size: 1em
|
||||||
|
|
||||||
|
&__input:checked + &__label &__button,
|
||||||
|
&__input:not(:checked) + &__label &__button
|
||||||
|
width: size = 1em
|
||||||
|
height: size
|
||||||
|
margin-top: -.15em
|
||||||
|
margin-right: .15em
|
||||||
|
border: 1px solid #bbb
|
||||||
|
border-radius: form_border_radius
|
||||||
|
box-shadow: inset 0 .1em .2em black(.1)
|
||||||
|
|
||||||
|
&__input:checked + &__label &__button
|
||||||
|
&:before
|
||||||
|
background-size: 100% 100%
|
||||||
|
background-repeat: no-repeat
|
||||||
|
|
||||||
|
&__input:enabled:active + &__label &__button,
|
||||||
|
&__input:focus + &__label &__button
|
||||||
|
background: #f4f4f4
|
||||||
|
|
||||||
|
.checkbox
|
||||||
|
&__input:checked + &__label &__button
|
||||||
|
&:before
|
||||||
|
center(.8em, .65em)
|
||||||
|
background-image: embedurl("check.svg")
|
||||||
|
.no-svg &:before
|
||||||
|
margin-top:-.5em;
|
||||||
|
font-size: 0.8em
|
||||||
|
font-weight:bold;
|
||||||
|
color: #444
|
||||||
|
content: "✓"
|
||||||
|
|
||||||
|
.radio
|
||||||
|
&__input:checked + &__label &__button,
|
||||||
|
&__input:not(:checked) + &__label &__button
|
||||||
|
border-radius: 50%
|
||||||
|
|
||||||
|
&__input:checked + &__label &__button
|
||||||
|
&:before
|
||||||
|
center(.5em)
|
||||||
|
background-image: embedurl("radio.svg")
|
||||||
|
.no-svg &:before
|
||||||
|
background: #444
|
||||||
|
border-radius: 50%
|
|
@ -0,0 +1 @@
|
||||||
|
<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><circle fill="#444" cx="5" cy="5" r="5"/></svg>
|
After Width: | Height: | Size: 111 B |
|
@ -0,0 +1,18 @@
|
||||||
|
# Code blocks
|
||||||
|
|
||||||
|
Nice code examples with highlighting.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<pre class="code"><code class="language-coffescript">alert 'Hello world!'</code></pre>
|
||||||
|
|
||||||
|
<div class="text">
|
||||||
|
<pre><code class="language-coffescript">alert 'Hello world!'</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
* [highlight.js](http://softwaremaniacs.org/soft/highlight/en/).
|
||||||
|
* [docpad-plugin-highlightjs](https://github.com/docpad/docpad-plugin-highlightjs) for DocPad.
|
|
@ -0,0 +1 @@
|
||||||
|
<pre class="code"><code class="language-javascript">alert('Hello world!');</code></pre>
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Code blocks
|
||||||
|
|
||||||
|
modules_default_skin ?= true
|
||||||
|
code_default_skin ?= false
|
||||||
|
|
||||||
|
.code,
|
||||||
|
.text code,
|
||||||
|
.text kbd,
|
||||||
|
.text pre,
|
||||||
|
.text pre *
|
||||||
|
font-family: Consolas, "Lucida Console", Monaco, "DejaVu Sans Mono", monospace
|
||||||
|
|
||||||
|
.code
|
||||||
|
display: block
|
||||||
|
white-space: pre-wrap
|
||||||
|
-moz-tab-size: 4
|
||||||
|
-o-tab-size: 4
|
||||||
|
tab-size: 4
|
||||||
|
|
||||||
|
code
|
||||||
|
display: block
|
||||||
|
font-size: 14px
|
||||||
|
line-height: 1.3
|
||||||
|
|
||||||
|
.indent
|
||||||
|
display: inline-block
|
||||||
|
width: 2.2em
|
||||||
|
|
||||||
|
if modules_default_skin or code_default_skin
|
||||||
|
|
||||||
|
@import 'tomorrow'
|
||||||
|
|
||||||
|
code
|
||||||
|
padding: spacer
|
||||||
|
background: #fff
|
||||||
|
background: white(.7)
|
||||||
|
border-radius: 3px
|
||||||
|
border: 1px solid #ccc
|
||||||
|
border-color: black(.2)
|
||||||
|
|
||||||
|
// Enable code in .text blocks
|
||||||
|
.text pre
|
||||||
|
@extend .code
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Tomorrow theme
|
||||||
|
// Theme from: http://jmblog.github.com/color-themes-for-google-code-highlightjs
|
||||||
|
|
||||||
|
.tomorrow-comment,
|
||||||
|
.comment,
|
||||||
|
.title
|
||||||
|
color: #8e908c
|
||||||
|
|
||||||
|
.tomorrow-red,
|
||||||
|
.variable,
|
||||||
|
.attribute,
|
||||||
|
.tag,
|
||||||
|
.regexp,
|
||||||
|
.ruby .constant,
|
||||||
|
.xml .tag .title,
|
||||||
|
.xml .pi,
|
||||||
|
.xml .doctype,
|
||||||
|
.html .doctype,
|
||||||
|
.css .id,
|
||||||
|
.css .class,
|
||||||
|
.css .pseudo
|
||||||
|
color: #c82829
|
||||||
|
|
||||||
|
.tomorrow-orange,
|
||||||
|
.number,
|
||||||
|
.codeprocessor,
|
||||||
|
.built_in,
|
||||||
|
.literal,
|
||||||
|
.params,
|
||||||
|
.constant
|
||||||
|
color: #f5871f
|
||||||
|
|
||||||
|
.tomorrow-yellow,
|
||||||
|
.class,
|
||||||
|
.ruby .class .title,
|
||||||
|
.css .rules .attribute
|
||||||
|
color: #eab700
|
||||||
|
|
||||||
|
.tomorrow-green,
|
||||||
|
.string,
|
||||||
|
.value,
|
||||||
|
.inheritance,
|
||||||
|
.header,
|
||||||
|
.ruby .symbol,
|
||||||
|
.xml .cdata
|
||||||
|
color: #718c00
|
||||||
|
|
||||||
|
.tomorrow-aqua,
|
||||||
|
.css .hexcolor
|
||||||
|
color: #3e999f
|
||||||
|
|
||||||
|
.tomorrow-blue,
|
||||||
|
.function,
|
||||||
|
.python .decorator,
|
||||||
|
.python .title,
|
||||||
|
.ruby .function .title,
|
||||||
|
.ruby .title .keyword,
|
||||||
|
.perl .sub,
|
||||||
|
.javascript .title,
|
||||||
|
.coffeescript .title
|
||||||
|
color: #4271ae
|
||||||
|
|
||||||
|
.tomorrow-purple,
|
||||||
|
.keyword,
|
||||||
|
.javascript .function
|
||||||
|
color: #8959a8
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Fade
|
||||||
|
|
||||||
|
Fading text.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="fade" title="Very long text">Very long text</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
Works best in Webkits (via `mask-image`). Works acceptable in Firefox (via SVG mask): fade width is fixed. Fades with ellipsis in any IE.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<p class="fade fixie" style="width:300px"></p>
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Fading text
|
||||||
|
// Based on http://mir.aculo.us/2012/09/16/masking-html-elements-with-gradient-based-fadeouts/ + thanks to @kizu
|
||||||
|
|
||||||
|
.fade
|
||||||
|
display: block
|
||||||
|
overflow: hidden
|
||||||
|
white-space: nowrap
|
||||||
|
-webkit-mask-image: -webkit-linear-gradient(right, transparent 0, #000 3em) // Webkit
|
||||||
|
mask: embedurl("mask.svg#fade-mask") // Firefox
|
||||||
|
-ms-text-overflow: ellipsis // IE
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"><mask maskContentUnits="objectBoundingBox"><linearGradient id="a"><stop stop-color="#fff" offset=".7"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><rect width="1" height="1" fill="url(#a)"/></mask></svg>
|
After Width: | Height: | Size: 269 B |
|
@ -0,0 +1,9 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<mask id="fade-mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
|
||||||
|
<linearGradient id="g">
|
||||||
|
<stop stop-color="#fff" stop-opacity="1" offset=".7"></stop>
|
||||||
|
<stop stop-color="#fff" stop-opacity="0" offset="1"></stop>
|
||||||
|
</linearGradient>
|
||||||
|
<rect x="0" y="0" width="1" height="1" fill="url(#g)"></rect>
|
||||||
|
</mask>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 384 B |
|
@ -0,0 +1,39 @@
|
||||||
|
# Flippable pane
|
||||||
|
|
||||||
|
Vertical or horizontal flippable pane. With 3D animation.
|
||||||
|
|
||||||
|
|
||||||
|
# Markup
|
||||||
|
|
||||||
|
<div class="flippable js-flip" data-component="flippable">
|
||||||
|
<div class="flippable__front">Front</div>
|
||||||
|
<div class="flippable__back">Back</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Modifiers
|
||||||
|
|
||||||
|
### .flippable.flippable_vertical
|
||||||
|
|
||||||
|
Vertical rotation (horizontal by default).
|
||||||
|
|
||||||
|
|
||||||
|
## States
|
||||||
|
|
||||||
|
### .flippable.is-flipped
|
||||||
|
|
||||||
|
Back side is visible.
|
||||||
|
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
### flipped.tamia
|
||||||
|
|
||||||
|
Fires on every flip. Argument will be `true` if back side is visible.
|
||||||
|
|
||||||
|
|
||||||
|
## JS Hooks
|
||||||
|
|
||||||
|
### .js-flip
|
||||||
|
|
||||||
|
Element that flips pane when clicked.
|
|
@ -0,0 +1,4 @@
|
||||||
|
<div class="flippable js-flip" data-component="flippable" style="width:200px; height:200px">
|
||||||
|
<div class="flippable__front fixie" style="padding:20px; background:#8FA1B3"></div>
|
||||||
|
<div class="flippable__back fixie" style="padding:20px; background:#EBCB8B"></div>
|
||||||
|
</div>
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Flippable pane
|
||||||
|
|
||||||
|
.flippable
|
||||||
|
no-select()
|
||||||
|
position: relative
|
||||||
|
perspective: 600px
|
||||||
|
cursor: default
|
||||||
|
|
||||||
|
&__front,
|
||||||
|
&__back
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: inherit
|
||||||
|
height: inherit
|
||||||
|
transform-style: preserve-3d
|
||||||
|
backface-visibility: hidden
|
||||||
|
transition: all .4s ease-out-back
|
||||||
|
&__front
|
||||||
|
z-index: 900
|
||||||
|
transform: rotateY(0deg) rotateX(0deg)
|
||||||
|
&__back
|
||||||
|
z-index:800;
|
||||||
|
transform: rotateY(-180deg)
|
||||||
|
&_vertical &__back
|
||||||
|
transform: rotateX(-180deg)
|
||||||
|
|
||||||
|
&.is-flipped &__front
|
||||||
|
transform: rotateY(180deg)
|
||||||
|
&_vertical.is-flipped &__front
|
||||||
|
transform: rotateX(180deg)
|
||||||
|
|
||||||
|
.is-flipped &__back
|
||||||
|
transform: rotateY(0deg) rotateX(0deg)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
# Flippable pane
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
$ = jQuery
|
||||||
|
|
||||||
|
class Flippable extends Component
|
||||||
|
init: ->
|
||||||
|
if @elem.hasClass('js-flip')
|
||||||
|
@on('click', @toggle)
|
||||||
|
else
|
||||||
|
@on('click', 'flip', @toggle)
|
||||||
|
|
||||||
|
toggle: ->
|
||||||
|
@toggleState('flipped')
|
||||||
|
@elem.trigger('flipped.tamia', @hasState('flipped'))
|
||||||
|
|
||||||
|
tamia.initComponents(flippable: Flippable)
|
|
@ -0,0 +1,38 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var $, Flippable, _ref,
|
||||||
|
__hasProp = {}.hasOwnProperty,
|
||||||
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||||
|
|
||||||
|
$ = jQuery;
|
||||||
|
|
||||||
|
Flippable = (function(_super) {
|
||||||
|
__extends(Flippable, _super);
|
||||||
|
|
||||||
|
function Flippable() {
|
||||||
|
_ref = Flippable.__super__.constructor.apply(this, arguments);
|
||||||
|
return _ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flippable.prototype.init = function() {
|
||||||
|
if (this.elem.hasClass('js-flip')) {
|
||||||
|
return this.on('click', this.toggle);
|
||||||
|
} else {
|
||||||
|
return this.on('click', 'flip', this.toggle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Flippable.prototype.toggle = function() {
|
||||||
|
this.toggleState('flipped');
|
||||||
|
return this.elem.trigger('flipped.tamia', this.hasState('flipped'));
|
||||||
|
};
|
||||||
|
|
||||||
|
return Flippable;
|
||||||
|
|
||||||
|
})(Component);
|
||||||
|
|
||||||
|
tamia.initComponents({
|
||||||
|
flippable: Flippable
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this);
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Form
|
||||||
|
|
||||||
|
Basic form controls: inputs, textareas, buttons.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
Controls:
|
||||||
|
|
||||||
|
<input type="text" class="field" name="name">
|
||||||
|
<textarea type="text" class="field field_area" name="message"></textarea>
|
||||||
|
<input type="submit" class="button" value="Send!">
|
||||||
|
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
### enable.tamia / disable.tamia
|
||||||
|
|
||||||
|
Enables / disables all descendant form elements.
|
||||||
|
|
||||||
|
|
||||||
|
## Skin
|
||||||
|
|
||||||
|
Set `form_default_skin` or `modules_default_skin` to `true` to enable default skin.
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### form_focus_color
|
||||||
|
|
||||||
|
Type: CSS color value.
|
||||||
|
|
||||||
|
Color of focus otline.
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="form form_full">
|
||||||
|
<div class="form__row">
|
||||||
|
<input type="text" class="field" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form__row">
|
||||||
|
<button class="button fixie"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form form_inline">
|
||||||
|
<input type="text" class="field" placeholder="Name">
|
||||||
|
<button class="button fixie"></button>
|
||||||
|
</div>
|
|
@ -0,0 +1,136 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Basic form controls: inputs, textareas, buttons
|
||||||
|
|
||||||
|
// Disabled form element
|
||||||
|
.is-disabled
|
||||||
|
cursor: default
|
||||||
|
pointer-events: none
|
||||||
|
text-shadow: none
|
||||||
|
|
||||||
|
|
||||||
|
// Bones
|
||||||
|
|
||||||
|
.field,
|
||||||
|
.button
|
||||||
|
display: block
|
||||||
|
vertical-align: middle
|
||||||
|
font-size: 1em
|
||||||
|
line-height: 1
|
||||||
|
outline: 0
|
||||||
|
transition: opacity .25 ease-out
|
||||||
|
|
||||||
|
&_inline
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
&.is-disabled
|
||||||
|
opacity: .4
|
||||||
|
|
||||||
|
.field
|
||||||
|
// Hide IE10 clear button
|
||||||
|
&::-ms-clear
|
||||||
|
size: 0 // Not display:none because: http://bit.ly/1h3UlAH
|
||||||
|
|
||||||
|
.field_area
|
||||||
|
resize: vertical
|
||||||
|
|
||||||
|
.button
|
||||||
|
no-select()
|
||||||
|
position: relative // Fixes strange bugs in webkit
|
||||||
|
text-decoration: none
|
||||||
|
white-space: nowrap
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
// Fixing Mozilla's inner paddings
|
||||||
|
// https://github.com/nanoblocks/nanoblocks/blob/gh-pages/blocks/button/button.styl
|
||||||
|
&::-moz-focus-inner
|
||||||
|
padding: 0
|
||||||
|
border: none
|
||||||
|
|
||||||
|
.form
|
||||||
|
&_inline .field,
|
||||||
|
&_inline .button,
|
||||||
|
&_inline .select,
|
||||||
|
&_inline .password
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
&_full .field,
|
||||||
|
&_full .button,
|
||||||
|
&_full .select,
|
||||||
|
&_full .password
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
&__group
|
||||||
|
space(2)
|
||||||
|
|
||||||
|
&__row
|
||||||
|
space()
|
||||||
|
&:last-child
|
||||||
|
space(0)
|
||||||
|
|
||||||
|
&__left
|
||||||
|
float: left
|
||||||
|
|
||||||
|
&__right
|
||||||
|
float: right
|
||||||
|
|
||||||
|
|
||||||
|
// Default skin
|
||||||
|
|
||||||
|
modules_default_skin ?= true
|
||||||
|
form_default_skin ?= false
|
||||||
|
|
||||||
|
|
||||||
|
if modules_default_skin or form_default_skin
|
||||||
|
|
||||||
|
.field,
|
||||||
|
.button
|
||||||
|
height: 2em
|
||||||
|
border-radius: form_border_radius
|
||||||
|
|
||||||
|
&:focus
|
||||||
|
outline: 0
|
||||||
|
border-color: form_focus_color
|
||||||
|
|
||||||
|
.field,
|
||||||
|
.button:active
|
||||||
|
transition: border-color .1s ease-in-out, box-shadow .1s ease-in-out
|
||||||
|
|
||||||
|
.field
|
||||||
|
padding: .3em .4em
|
||||||
|
background: #fff
|
||||||
|
border: 1px solid #bbb
|
||||||
|
box-shadow: inset 0 .1em .2em black(.1)
|
||||||
|
|
||||||
|
&:focus
|
||||||
|
box-shadow: inset 0 .1em .2em black(.1), 0 0 .4em rgba(form_focus_color, .75)
|
||||||
|
|
||||||
|
&_area
|
||||||
|
height: auto
|
||||||
|
|
||||||
|
.button
|
||||||
|
height: 2em
|
||||||
|
padding: .45em 1.5em .35em;
|
||||||
|
background: #dfdfdf
|
||||||
|
background: linear-gradient(to bottom, #fefefe, #eaeaea)
|
||||||
|
border: 1px solid #bbb
|
||||||
|
border-bottom-color: #aaa
|
||||||
|
color: #555
|
||||||
|
border-radius: form_border_radius
|
||||||
|
box-shadow: 0 .1em .1em black(.05)
|
||||||
|
text-shadow: 0 1px 0 white(.4)
|
||||||
|
|
||||||
|
&:focus
|
||||||
|
box-shadow: 0 0 .4em rgba(form_focus_color, .75)
|
||||||
|
|
||||||
|
&:not(.is-disabled):hover
|
||||||
|
background: linear-gradient(to bottom, #fff, #f0f0f0)
|
||||||
|
color: #333
|
||||||
|
|
||||||
|
&:not(.is-disabled):active
|
||||||
|
padding-top: .55em
|
||||||
|
padding-bottom: .25em
|
||||||
|
background: #cacaca
|
||||||
|
background: linear-gradient(to bottom, #aaa, #dfdfdf)
|
||||||
|
box-shadow: 0 0 .4em rgba(form_focus_color, .75), inset 0 .1em .2em black(.2), 0 .025em .05em black(.05)
|
||||||
|
border-color: form_focus_color
|
||||||
|
border-top-color: #888
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
# Basic form controls
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
$ = jQuery
|
||||||
|
|
||||||
|
|
||||||
|
_formElementsSelector = '.field,.button,.disablable'
|
||||||
|
_disabledClass = 'is-disabled'
|
||||||
|
|
||||||
|
_enableDisable = (elem, enable) ->
|
||||||
|
formElements = ($ elem).find(_formElementsSelector).addBack(_formElementsSelector)
|
||||||
|
formElements[if enable then 'removeClass' else 'addClass'](_disabledClass)
|
||||||
|
formElements.attr('disabled', !enable)
|
||||||
|
|
||||||
|
|
||||||
|
# Events
|
||||||
|
tamia.registerEvents(
|
||||||
|
###
|
||||||
|
Enables all descendant form elements.
|
||||||
|
###
|
||||||
|
enable: (elem) ->
|
||||||
|
_enableDisable elem, true
|
||||||
|
|
||||||
|
###
|
||||||
|
Disables all descendant form elements.
|
||||||
|
###
|
||||||
|
disable: (elem) ->
|
||||||
|
_enableDisable elem, false
|
||||||
|
)
|
|
@ -0,0 +1,35 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var $, _disabledClass, _enableDisable, _formElementsSelector;
|
||||||
|
|
||||||
|
$ = jQuery;
|
||||||
|
|
||||||
|
_formElementsSelector = '.field,.button,.disablable';
|
||||||
|
|
||||||
|
_disabledClass = 'is-disabled';
|
||||||
|
|
||||||
|
_enableDisable = function(elem, enable) {
|
||||||
|
var formElements;
|
||||||
|
formElements = ($(elem)).find(_formElementsSelector).addBack(_formElementsSelector);
|
||||||
|
formElements[enable ? 'removeClass' : 'addClass'](_disabledClass);
|
||||||
|
return formElements.attr('disabled', !enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
tamia.registerEvents({
|
||||||
|
/*
|
||||||
|
Enables all descendant form elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enable: function(elem) {
|
||||||
|
return _enableDisable(elem, true);
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
Disables all descendant form elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
disable: function(elem) {
|
||||||
|
return _enableDisable(elem, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this);
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Unordered list
|
||||||
|
|
||||||
|
Unordered list with dashes (—) as bullets.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<ul class="list">
|
||||||
|
<li>Dog</li>
|
||||||
|
<li>Cat</li>
|
||||||
|
<li>Mouse</li>
|
||||||
|
<li>Moose</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### list_inside
|
||||||
|
|
||||||
|
Type: Boolean, default: `false`.
|
||||||
|
|
||||||
|
If `true` places bullets inside container (by default bullets are outside).
|
||||||
|
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
1. If `list_inside` is `false` (default) automatically places bullets inside container (like `list_inside = true` does) when window width is less than `max_width` global variable.
|
||||||
|
|
||||||
|
2. `UL`s inside `.text` class are treated as `.list`.
|
|
@ -0,0 +1,6 @@
|
||||||
|
<ul class="list">
|
||||||
|
<li class="fixie"></li>
|
||||||
|
<li class="fixie"></li>
|
||||||
|
<li class="fixie"></li>
|
||||||
|
<li class="fixie"></li>
|
||||||
|
</ul>
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Unordered list with dashes as bullets
|
||||||
|
|
||||||
|
// Place bullets inside container (by default bullets are outside).
|
||||||
|
list_inside ?= false
|
||||||
|
|
||||||
|
|
||||||
|
.list
|
||||||
|
> li
|
||||||
|
position: relative
|
||||||
|
padding-left: 1.3em
|
||||||
|
margin-left: -1.3em unless list_inside
|
||||||
|
> li:before
|
||||||
|
position: absolute
|
||||||
|
left: 0
|
||||||
|
content: "\2014\a0"
|
||||||
|
|
||||||
|
ul
|
||||||
|
margin-left: 1.3em
|
||||||
|
|
||||||
|
li > ul,
|
||||||
|
li > ol
|
||||||
|
margin-bottom: 0
|
||||||
|
|
||||||
|
.text
|
||||||
|
ul
|
||||||
|
@extend .list
|
||||||
|
|
||||||
|
if not list_inside and max_width
|
||||||
|
+below(max_width)
|
||||||
|
.list > li,
|
||||||
|
.text ul > li
|
||||||
|
margin-left: 0
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Media object
|
||||||
|
|
||||||
|
Media object from OOCSS.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="media">
|
||||||
|
<img src="http://placedog.com/200/200" alt="" class="media__img">
|
||||||
|
<p class="media__body">Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice “without pictures or conversation?”</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Modifiers
|
||||||
|
|
||||||
|
### .media__img.media__img_rev
|
||||||
|
|
||||||
|
Reversed image location (right instead of left).
|
||||||
|
|
||||||
|
```html
|
||||||
|
<img src="http://placedog.com/200/200" alt="" class="media__img media__img_rev">
|
||||||
|
```
|
|
@ -0,0 +1,4 @@
|
||||||
|
<div class="media">
|
||||||
|
<img class="media__img fixie" src="http://placedog.com/150/100">
|
||||||
|
<p class="media__body fixie"></p>
|
||||||
|
</div>
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Media object
|
||||||
|
// Based on https://github.com/csswizardry/inuit.css/blob/master/objects/_media.scss
|
||||||
|
|
||||||
|
.media
|
||||||
|
clearfix()
|
||||||
|
display: block
|
||||||
|
|
||||||
|
&__img
|
||||||
|
float: left
|
||||||
|
margin-right: spacer
|
||||||
|
&__img_rev
|
||||||
|
float: right
|
||||||
|
margin-right: 0
|
||||||
|
margin-left: spacer
|
||||||
|
|
||||||
|
&__body
|
||||||
|
overflow: hidden
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Password field
|
||||||
|
|
||||||
|
Password field with toggle to show characters.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="password" data-component="password">
|
||||||
|
<span class="password__toggle js-toggle"></span>
|
||||||
|
<input type="password" class="password__field field js-field">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## States
|
||||||
|
|
||||||
|
### .password.is-ok
|
||||||
|
|
||||||
|
Browser is supported.
|
||||||
|
|
||||||
|
### .password.is-unlocked
|
||||||
|
|
||||||
|
Password characters are visible.
|
||||||
|
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
IE9+.
|
||||||
|
|
||||||
|
|
||||||
|
## Skin
|
||||||
|
|
||||||
|
Set `password_default_skin` or `modules_default_skin` to `true` to enable default skin.
|
|
@ -0,0 +1,4 @@
|
||||||
|
<div class="password password_inline" data-component="password">
|
||||||
|
<span class="password__toggle js-toggle"></span>
|
||||||
|
<input type="password" class="password__field field js-field">
|
||||||
|
</div>
|
|
@ -0,0 +1,60 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Password field with toggle to show characters
|
||||||
|
// Dependencies: form
|
||||||
|
|
||||||
|
// Bones
|
||||||
|
|
||||||
|
.password
|
||||||
|
position: relative
|
||||||
|
display: block
|
||||||
|
|
||||||
|
&_inline
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
&__field
|
||||||
|
position:relative;
|
||||||
|
width: 100%
|
||||||
|
z-index: 90
|
||||||
|
|
||||||
|
&__toggle
|
||||||
|
display: none
|
||||||
|
&.is-ok &__toggle
|
||||||
|
position: absolute
|
||||||
|
display: block
|
||||||
|
top: 0
|
||||||
|
bottom: 0
|
||||||
|
right: 0
|
||||||
|
cursor: pointer
|
||||||
|
z-index: 100
|
||||||
|
&:before
|
||||||
|
content: ""
|
||||||
|
position: absolute
|
||||||
|
top: 50%
|
||||||
|
left: 50%
|
||||||
|
transform: translate(-50%,-50%)
|
||||||
|
|
||||||
|
&.is-disabled &__toggle
|
||||||
|
opacity: .4
|
||||||
|
|
||||||
|
// Hide IE10 password visibility toggle
|
||||||
|
&::-ms-reveal
|
||||||
|
size: 0 // Not display:none because: http://bit.ly/1h3UlAH
|
||||||
|
|
||||||
|
|
||||||
|
// Default skin
|
||||||
|
|
||||||
|
modules_default_skin ?= true
|
||||||
|
password_default_skin ?= false
|
||||||
|
|
||||||
|
if modules_default_skin or password_default_skin
|
||||||
|
.password
|
||||||
|
&.is-ok &__toggle
|
||||||
|
width: 1.8em
|
||||||
|
&:before
|
||||||
|
tweak-inverted-text()
|
||||||
|
content: "abc"
|
||||||
|
font-size: .75em
|
||||||
|
letter-spacing: .1ex
|
||||||
|
&.is-ok.is-unlocked &__toggle:before
|
||||||
|
content: "●●●"
|
||||||
|
letter-spacing: 0
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
# Password field with toggle to show characters
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
$ = jQuery
|
||||||
|
|
||||||
|
supported = undefined
|
||||||
|
|
||||||
|
class Password extends Component
|
||||||
|
init: ->
|
||||||
|
@types =
|
||||||
|
locked: 'password'
|
||||||
|
unlocked: 'text'
|
||||||
|
|
||||||
|
@fieldElem = @find('field')
|
||||||
|
@toggleElem = @find('toggle')
|
||||||
|
|
||||||
|
# Mousedown instead of click to catch focused field
|
||||||
|
@on('mousedown', 'toggle', @toggle)
|
||||||
|
|
||||||
|
isSupported: ->
|
||||||
|
return supported unless supported is undefined
|
||||||
|
|
||||||
|
# IE8+
|
||||||
|
supported = $('<!--[if lte IE 8]><i></i><![endif]-->').find('i').length isnt 1
|
||||||
|
return supported
|
||||||
|
|
||||||
|
toggle: ->
|
||||||
|
focused = document.activeElement is @fieldElem[0]
|
||||||
|
locked = @hasState('unlocked')
|
||||||
|
|
||||||
|
fieldType = @fieldElem.attr('type')
|
||||||
|
|
||||||
|
@toggleState('unlocked')
|
||||||
|
|
||||||
|
if fieldType is @types.locked and not locked
|
||||||
|
@fieldElem.attr('type', @types.unlocked)
|
||||||
|
else if fieldType is @types.unlocked and locked
|
||||||
|
@fieldElem.attr('type', @types.locked)
|
||||||
|
|
||||||
|
if focused
|
||||||
|
setTimeout((=> @fieldElem.focus()), 0)
|
||||||
|
|
||||||
|
tamia.initComponents(password: Password)
|
|
@ -0,0 +1,64 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var $, Password, supported, _ref,
|
||||||
|
__hasProp = {}.hasOwnProperty,
|
||||||
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||||
|
|
||||||
|
$ = jQuery;
|
||||||
|
|
||||||
|
supported = void 0;
|
||||||
|
|
||||||
|
Password = (function(_super) {
|
||||||
|
__extends(Password, _super);
|
||||||
|
|
||||||
|
function Password() {
|
||||||
|
_ref = Password.__super__.constructor.apply(this, arguments);
|
||||||
|
return _ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
Password.prototype.init = function() {
|
||||||
|
this.types = {
|
||||||
|
locked: 'password',
|
||||||
|
unlocked: 'text'
|
||||||
|
};
|
||||||
|
this.fieldElem = this.find('field');
|
||||||
|
this.toggleElem = this.find('toggle');
|
||||||
|
return this.on('mousedown', 'toggle', this.toggle);
|
||||||
|
};
|
||||||
|
|
||||||
|
Password.prototype.isSupported = function() {
|
||||||
|
if (supported !== void 0) {
|
||||||
|
return supported;
|
||||||
|
}
|
||||||
|
supported = $('<!--[if lte IE 8]><i></i><![endif]-->').find('i').length !== 1;
|
||||||
|
return supported;
|
||||||
|
};
|
||||||
|
|
||||||
|
Password.prototype.toggle = function() {
|
||||||
|
var fieldType, focused, locked,
|
||||||
|
_this = this;
|
||||||
|
focused = document.activeElement === this.fieldElem[0];
|
||||||
|
locked = this.hasState('unlocked');
|
||||||
|
fieldType = this.fieldElem.attr('type');
|
||||||
|
this.toggleState('unlocked');
|
||||||
|
if (fieldType === this.types.locked && !locked) {
|
||||||
|
this.fieldElem.attr('type', this.types.unlocked);
|
||||||
|
} else if (fieldType === this.types.unlocked && locked) {
|
||||||
|
this.fieldElem.attr('type', this.types.locked);
|
||||||
|
}
|
||||||
|
if (focused) {
|
||||||
|
return setTimeout((function() {
|
||||||
|
return _this.fieldElem.focus();
|
||||||
|
}), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Password;
|
||||||
|
|
||||||
|
})(Component);
|
||||||
|
|
||||||
|
tamia.initComponents({
|
||||||
|
password: Password
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this);
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Print
|
||||||
|
|
||||||
|
Print stylesheet.
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### site_domain
|
||||||
|
|
||||||
|
Type: String.
|
||||||
|
|
||||||
|
Site domain (for example, `example.com`) that will be printed.
|
||||||
|
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
Use `.no-print` class to hide elements in print version and `.print` to show (hidden on screen).
|
|
@ -0,0 +1,103 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Print stylesheet
|
||||||
|
|
||||||
|
// Site domain (for example, `example.com`) that will be printed.
|
||||||
|
site_domain ?= false
|
||||||
|
|
||||||
|
@media print
|
||||||
|
|
||||||
|
@page
|
||||||
|
margin: .5cm
|
||||||
|
|
||||||
|
nav,
|
||||||
|
.social-likes,
|
||||||
|
.no-print
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.print
|
||||||
|
display: block
|
||||||
|
|
||||||
|
*
|
||||||
|
font-family: Cambria, Georgia, serif
|
||||||
|
color: #000 !important
|
||||||
|
background: transparent !important
|
||||||
|
float: none !important
|
||||||
|
width: auto !important
|
||||||
|
margin-left: 0 !important
|
||||||
|
margin-right: 0 !important
|
||||||
|
padding-left: 0 !important
|
||||||
|
padding-right: 0 !important
|
||||||
|
text-shadow: none !important
|
||||||
|
|
||||||
|
body
|
||||||
|
padding-bottom: 0
|
||||||
|
|
||||||
|
a
|
||||||
|
border: none !important
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6
|
||||||
|
font-family: Corbel, 'Helvetica Neue', Arial, sans-serif
|
||||||
|
page-break-inside: avoid
|
||||||
|
page-break-after: avoid
|
||||||
|
|
||||||
|
a:link:after,
|
||||||
|
a:visited:after
|
||||||
|
content: " (" attr(href) ")"
|
||||||
|
font-size: .9em
|
||||||
|
|
||||||
|
if site_domain
|
||||||
|
a[href^="/"]:link:after,
|
||||||
|
a[href^="/"]:visited:after
|
||||||
|
content: (" (http://" + site_domain) attr(href) ")"
|
||||||
|
font-size: .9em
|
||||||
|
|
||||||
|
a[href^="javascript:"]:after,
|
||||||
|
a[href^="#"]:after,
|
||||||
|
.footer a:after
|
||||||
|
content: ""
|
||||||
|
|
||||||
|
.header
|
||||||
|
margin-bottom: 2*spacer
|
||||||
|
border-bottom: 1pt solid #000
|
||||||
|
height: auto
|
||||||
|
|
||||||
|
.footer
|
||||||
|
position: static
|
||||||
|
margin-top: 2*spacer
|
||||||
|
border-top: 1pt solid #000
|
||||||
|
height: auto
|
||||||
|
a
|
||||||
|
text-decoration: none
|
||||||
|
|
||||||
|
if site_domain
|
||||||
|
.logo:before
|
||||||
|
content: url(/favicon.ico)
|
||||||
|
padding-right: 2px
|
||||||
|
vertical-align: middle
|
||||||
|
|
||||||
|
.logo a:link:after,
|
||||||
|
.logo a:visited:after
|
||||||
|
content: " — " + site_domain
|
||||||
|
|
||||||
|
p,
|
||||||
|
blockquote,
|
||||||
|
ul,
|
||||||
|
ol,
|
||||||
|
dl,
|
||||||
|
tr,
|
||||||
|
img
|
||||||
|
page-break-inside: avoid
|
||||||
|
|
||||||
|
p,
|
||||||
|
h2,
|
||||||
|
h3
|
||||||
|
orphans: 3
|
||||||
|
widows: 3
|
||||||
|
|
||||||
|
ul
|
||||||
|
margin-left: 1.2em !important
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Rich typograhy
|
||||||
|
|
||||||
|
Classes and tweaks for better typography.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
### Abbreviations with spacing
|
||||||
|
|
||||||
|
<div class="text">
|
||||||
|
<p><abbr>PNG</abbr>, <abbr>GIF</abbr> (animated or not) and <abbr>JPEG</abbr> formats.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### The best ampersand
|
||||||
|
|
||||||
|
Nuts <span class="amp">&</span> Bolts.
|
||||||
|
|
||||||
|
### Hanging punctuation
|
||||||
|
|
||||||
|
Awesome Web Typography with <span class="slaquo"> </span> <span class="hlaquo">“</span>Richtypo”'
|
||||||
|
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
* Enables ligatures in headings (h1—h6 inside .text and .alpha—.zeta).
|
||||||
|
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
* [richtypo.js](https://github.com/sapegin/richtypo.js) for Node.js.
|
||||||
|
* [wp-typohelper](https://github.com/sapegin/wp-typohelper) for Wordpress.
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Rich typograhy
|
||||||
|
|
||||||
|
// Abbreviations with spacing.
|
||||||
|
.abbr,
|
||||||
|
.text abbr
|
||||||
|
letter-spacing: 0.1em
|
||||||
|
margin-right: -0.1em
|
||||||
|
|
||||||
|
// The best ampersand.
|
||||||
|
.amp
|
||||||
|
font-family: Baskerville, Constantia, Palatino, "Palatino Linotype", "Book Antiqua", serif
|
||||||
|
font-style: italic
|
||||||
|
|
||||||
|
// Hanging punctuation.
|
||||||
|
.sbrace
|
||||||
|
margin-right: 0.3em
|
||||||
|
.hbrace
|
||||||
|
margin-left: -0.3em
|
||||||
|
.slaquo
|
||||||
|
margin-right: 0.42em
|
||||||
|
.hlaquo
|
||||||
|
margin-left: -0.42em
|
||||||
|
|
||||||
|
// Headings with ligatures.
|
||||||
|
.text h1, .alpha,
|
||||||
|
.text h2, .beta,
|
||||||
|
.text h3, .gamma,
|
||||||
|
.text h4, .delta,
|
||||||
|
.text h5, .epsilon,
|
||||||
|
.text h6, .zeta
|
||||||
|
enable-ligatures()
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Select
|
||||||
|
|
||||||
|
Select with custom design
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="select" data-component="select">
|
||||||
|
<div class="select__box js-box"></div>
|
||||||
|
<select class="select__select js-select">
|
||||||
|
<option selected>Please select an option</option>
|
||||||
|
<option>Dog</option>
|
||||||
|
<option>Cat</option>
|
||||||
|
<option>Mouse</option>
|
||||||
|
<option>Moose</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Skin
|
||||||
|
|
||||||
|
Set `select_default_skin` or `modules_default_skin` to `true` to enable default skin.
|
|
@ -0,0 +1 @@
|
||||||
|
<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h10l-5 9-5-9z" fill="#444"/></svg>
|
After Width: | Height: | Size: 111 B |
|
@ -0,0 +1,10 @@
|
||||||
|
<div class="select select_inline" data-component="select">
|
||||||
|
<div class="select__box js-box"></div>
|
||||||
|
<select class="select__select js-select">
|
||||||
|
<option selected>Please select an option</option>
|
||||||
|
<option class="fixie"></option>
|
||||||
|
<option class="fixie"></option>
|
||||||
|
<option class="fixie"></option>
|
||||||
|
<option class="fixie"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
|
@ -0,0 +1,86 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Select with custom design
|
||||||
|
// Dependencies: form
|
||||||
|
|
||||||
|
// Bones
|
||||||
|
|
||||||
|
.select
|
||||||
|
no-select()
|
||||||
|
position: relative
|
||||||
|
display: block
|
||||||
|
overflow: hidden
|
||||||
|
font-size: 1em
|
||||||
|
|
||||||
|
&_inline
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
&__select
|
||||||
|
position: absolute
|
||||||
|
bottom: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
opacity: 0
|
||||||
|
z-index: 2
|
||||||
|
cursor: default
|
||||||
|
transform: scaleY(2) // Select height could be smaller than box height
|
||||||
|
transform-origin: 0 100% // Fixes dropdown position on Windows
|
||||||
|
|
||||||
|
&__box
|
||||||
|
display: block
|
||||||
|
vertical-align: middle
|
||||||
|
line-height: 1
|
||||||
|
white-space: nowrap
|
||||||
|
overflow: hidden
|
||||||
|
text-overflow: ellipsis
|
||||||
|
|
||||||
|
&:after
|
||||||
|
content: ""
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
bottom: 0
|
||||||
|
right: 0
|
||||||
|
z-index: 1
|
||||||
|
|
||||||
|
&.is-disabled
|
||||||
|
opacity: .4
|
||||||
|
|
||||||
|
|
||||||
|
// Default skin
|
||||||
|
|
||||||
|
modules_default_skin ?= true
|
||||||
|
select_default_skin ?= false
|
||||||
|
|
||||||
|
if modules_default_skin or select_default_skin
|
||||||
|
.select
|
||||||
|
border: 1px solid #bbb
|
||||||
|
border-bottom-color: #aaa
|
||||||
|
border-radius: form_border_radius
|
||||||
|
transition: border-color .1s ease-in-out, box-shadow .1s ease-in-out
|
||||||
|
|
||||||
|
&__box
|
||||||
|
height: 2em
|
||||||
|
padding: .5em 1.5em .5em .5em
|
||||||
|
background: #f4f4f4
|
||||||
|
background: linear-gradient(to bottom, #fefefe, #f4f4f4)
|
||||||
|
line-height: 1
|
||||||
|
color: #555
|
||||||
|
|
||||||
|
&:after
|
||||||
|
top: 50%
|
||||||
|
right: .3em
|
||||||
|
width: .8em
|
||||||
|
height: .7em
|
||||||
|
margin-top: -.3em
|
||||||
|
background: embedurl("arrow.svg") no-repeat
|
||||||
|
background-size: 100% 100%
|
||||||
|
.no-svg &:after
|
||||||
|
content: "▼"
|
||||||
|
padding-right: .2em
|
||||||
|
text-align: center
|
||||||
|
vertical-align: middle
|
||||||
|
font-size: 1em
|
||||||
|
line-height: 2em
|
||||||
|
|
||||||
|
&.is-focused
|
||||||
|
border-color: form_focus_color
|
||||||
|
box-shadow: 0 0 .4em rgba(form_focus_color, .75)
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
# Select with custom design
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
$ = jQuery
|
||||||
|
|
||||||
|
class Select extends Component
|
||||||
|
init: ->
|
||||||
|
@selectElem = @find('select')
|
||||||
|
@boxElem = @find('box')
|
||||||
|
|
||||||
|
@on('focus', 'select', @focus)
|
||||||
|
@on('blur', 'select', @blur)
|
||||||
|
@on('change', 'select', @change)
|
||||||
|
|
||||||
|
@change()
|
||||||
|
|
||||||
|
focus: ->
|
||||||
|
@addState('focused')
|
||||||
|
|
||||||
|
blur: ->
|
||||||
|
@removeState('focused')
|
||||||
|
|
||||||
|
change: ->
|
||||||
|
@boxElem.text(@selectElem.find(':selected').text())
|
||||||
|
|
||||||
|
tamia.initComponents(select: Select)
|
|
@ -0,0 +1,46 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var $, Select, _ref,
|
||||||
|
__hasProp = {}.hasOwnProperty,
|
||||||
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||||
|
|
||||||
|
$ = jQuery;
|
||||||
|
|
||||||
|
Select = (function(_super) {
|
||||||
|
__extends(Select, _super);
|
||||||
|
|
||||||
|
function Select() {
|
||||||
|
_ref = Select.__super__.constructor.apply(this, arguments);
|
||||||
|
return _ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
Select.prototype.init = function() {
|
||||||
|
this.selectElem = this.find('select');
|
||||||
|
this.boxElem = this.find('box');
|
||||||
|
this.on('focus', 'select', this.focus);
|
||||||
|
this.on('blur', 'select', this.blur);
|
||||||
|
this.on('change', 'select', this.change);
|
||||||
|
return this.change();
|
||||||
|
};
|
||||||
|
|
||||||
|
Select.prototype.focus = function() {
|
||||||
|
return this.addState('focused');
|
||||||
|
};
|
||||||
|
|
||||||
|
Select.prototype.blur = function() {
|
||||||
|
return this.removeState('focused');
|
||||||
|
};
|
||||||
|
|
||||||
|
Select.prototype.change = function() {
|
||||||
|
return this.boxElem.text(this.selectElem.find(':selected').text());
|
||||||
|
};
|
||||||
|
|
||||||
|
return Select;
|
||||||
|
|
||||||
|
})(Component);
|
||||||
|
|
||||||
|
tamia.initComponents({
|
||||||
|
select: Select
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this);
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Spinner
|
||||||
|
|
||||||
|
Loading indicator (spinner) with animation.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="spinner"></div>
|
||||||
|
|
||||||
|
<div class="is-loading">
|
||||||
|
<div class="loader"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
`.loader` is the same as `.spinner` but it’s hidden by default. It’s visible only when `.is-loading` state is set on ancestor element.
|
||||||
|
|
||||||
|
## Modifiers
|
||||||
|
|
||||||
|
### .spinner.spinner_big
|
||||||
|
|
||||||
|
Bigger size.
|
||||||
|
|
||||||
|
|
||||||
|
## More sizes
|
||||||
|
|
||||||
|
You can set any spinner size changing `font-size` property.
|
||||||
|
|
||||||
|
.spinner_huge
|
||||||
|
font-size: 64px
|
||||||
|
|
||||||
|
<div class="spinner spinner_huge"></div>
|
||||||
|
|
||||||
|
|
||||||
|
## Component loading indicator
|
||||||
|
|
||||||
|
$('.pony').trigger('loading-start.tamia'); // Show loader
|
||||||
|
$('.pony').trigger('loading-stop.tamia'); // Hide loader
|
||||||
|
|
||||||
|
That will blocks all container’s content with a semi transparent layer and shows spinner in the middle.
|
||||||
|
|
||||||
|
To change shade layer’s color set `loader_shade_color` variable.
|
||||||
|
|
||||||
|
|
||||||
|
## IE 8—9 callback
|
||||||
|
|
||||||
|
Copy `spinner.gif` to your images folder and set `spinner_fallback_gif` variable to its URL.
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="spinner"></div>
|
|
@ -0,0 +1,81 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Spinner
|
||||||
|
// Based on http://codepen.io/beben-koben/pen/JcGnK
|
||||||
|
|
||||||
|
spinner_fallback_gif ?= false
|
||||||
|
loader_shade_color ?= white(.8)
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes spinner-rotate
|
||||||
|
0%
|
||||||
|
transform: rotate(0deg)
|
||||||
|
100%
|
||||||
|
transform: rotate(360deg)
|
||||||
|
|
||||||
|
|
||||||
|
// Regular spinner
|
||||||
|
.spinner,
|
||||||
|
.loader
|
||||||
|
display: inline-block
|
||||||
|
width: .25em
|
||||||
|
height: .25em
|
||||||
|
margin: .5em .2em
|
||||||
|
opacity: .7
|
||||||
|
border-radius: 50%
|
||||||
|
font-size: 16px
|
||||||
|
box-shadow: 0 -.4em 0 0 rgba(0,0,0,1), -.28em -.28em 0 0 rgba(0,0,0,.75), -.4em 0 0 0 rgba(0,0,0,.5), -.28em .28em 0 0 rgba(0,0,0,.25)
|
||||||
|
|
||||||
|
&_big
|
||||||
|
font-size: 32px
|
||||||
|
|
||||||
|
|
||||||
|
// Loader
|
||||||
|
.loader
|
||||||
|
visibility: hidden
|
||||||
|
opacity: 0
|
||||||
|
transition: visibility 0s .3s, opacity .3s ease-out
|
||||||
|
|
||||||
|
.is-loading &
|
||||||
|
visibility: visible
|
||||||
|
opacity: 1
|
||||||
|
transition: opacity .5s ease-out
|
||||||
|
|
||||||
|
|
||||||
|
// Enable animation only when spinner is visible to increase page performance
|
||||||
|
.spinner,
|
||||||
|
.is-loading .loader
|
||||||
|
animation: .85s spinner-rotate steps(9) infinite
|
||||||
|
|
||||||
|
.spinner.is-hidden,
|
||||||
|
.loader.is-hidden
|
||||||
|
animation: none
|
||||||
|
|
||||||
|
|
||||||
|
// Loader shade
|
||||||
|
.loader-wrapper
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
.loader-shade
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
opacity: 0
|
||||||
|
background: loader_shade_color
|
||||||
|
border-radius: inherit
|
||||||
|
z-index: 99999
|
||||||
|
transition: opacity .15s ease-out
|
||||||
|
|
||||||
|
.is-loading &
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
|
||||||
|
// Fallback GIF image for browsers that don’t support CSS animations
|
||||||
|
if spinner_fallback_gif
|
||||||
|
.no-cssanimations .spinner
|
||||||
|
width: 16px
|
||||||
|
height: 16px
|
||||||
|
margin: 0
|
||||||
|
opacity: 1
|
||||||
|
background: url(spinner_fallback_gif)
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
# Spinner
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
$ = jQuery
|
||||||
|
|
||||||
|
|
||||||
|
_wrapperClass = 'loader-wrapper'
|
||||||
|
_shadeSelector = '.loader-shade'
|
||||||
|
_loaderTmpl = '''
|
||||||
|
<div class="loader-shade">
|
||||||
|
<div class="l-center">
|
||||||
|
<div class="l-center-i">
|
||||||
|
<div class="spinner spinner_big"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Loader extends Component
|
||||||
|
init: ->
|
||||||
|
@initHtml()
|
||||||
|
setTimeout((=> @addState('loading')), 0)
|
||||||
|
|
||||||
|
destroy: ->
|
||||||
|
@removeState('loading')
|
||||||
|
@elem.find(_shadeSelector).afterTransition(=>
|
||||||
|
@elem.removeClass(_wrapperClass)
|
||||||
|
@loader.remove()
|
||||||
|
)
|
||||||
|
|
||||||
|
initHtml: ->
|
||||||
|
@elem.addClass(_wrapperClass)
|
||||||
|
@loader = $(_loaderTmpl)
|
||||||
|
@elem.append(@loader)
|
||||||
|
|
||||||
|
|
||||||
|
# Events
|
||||||
|
tamia.registerEvents(
|
||||||
|
'loading-start': (elem) ->
|
||||||
|
container = $(elem)
|
||||||
|
return if container.data('loader')
|
||||||
|
container.data('loader', new Loader(elem))
|
||||||
|
|
||||||
|
'loading-stop': (elem) ->
|
||||||
|
container = $(elem)
|
||||||
|
loader = container.data('loader')
|
||||||
|
return if not loader
|
||||||
|
loader.destroy()
|
||||||
|
container.removeData('loader')
|
||||||
|
)
|
|
@ -0,0 +1,71 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var $, Loader, _loaderTmpl, _ref, _shadeSelector, _wrapperClass,
|
||||||
|
__hasProp = {}.hasOwnProperty,
|
||||||
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||||
|
|
||||||
|
$ = jQuery;
|
||||||
|
|
||||||
|
_wrapperClass = 'loader-wrapper';
|
||||||
|
|
||||||
|
_shadeSelector = '.loader-shade';
|
||||||
|
|
||||||
|
_loaderTmpl = '<div class="loader-shade">\n <div class="l-center">\n <div class="l-center-i">\n <div class="spinner spinner_big"></div>\n </div>\n </div>\n</div>';
|
||||||
|
|
||||||
|
Loader = (function(_super) {
|
||||||
|
__extends(Loader, _super);
|
||||||
|
|
||||||
|
function Loader() {
|
||||||
|
_ref = Loader.__super__.constructor.apply(this, arguments);
|
||||||
|
return _ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader.prototype.init = function() {
|
||||||
|
var _this = this;
|
||||||
|
this.initHtml();
|
||||||
|
return setTimeout((function() {
|
||||||
|
return _this.addState('loading');
|
||||||
|
}), 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
Loader.prototype.destroy = function() {
|
||||||
|
var _this = this;
|
||||||
|
this.removeState('loading');
|
||||||
|
return this.elem.find(_shadeSelector).afterTransition(function() {
|
||||||
|
_this.elem.removeClass(_wrapperClass);
|
||||||
|
return _this.loader.remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Loader.prototype.initHtml = function() {
|
||||||
|
this.elem.addClass(_wrapperClass);
|
||||||
|
this.loader = $(_loaderTmpl);
|
||||||
|
return this.elem.append(this.loader);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Loader;
|
||||||
|
|
||||||
|
})(Component);
|
||||||
|
|
||||||
|
tamia.registerEvents({
|
||||||
|
'loading-start': function(elem) {
|
||||||
|
var container;
|
||||||
|
container = $(elem);
|
||||||
|
if (container.data('loader')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return container.data('loader', new Loader(elem));
|
||||||
|
},
|
||||||
|
'loading-stop': function(elem) {
|
||||||
|
var container, loader;
|
||||||
|
container = $(elem);
|
||||||
|
loader = container.data('loader');
|
||||||
|
if (!loader) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loader.destroy();
|
||||||
|
return container.removeData('loader');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this);
|
After Width: | Height: | Size: 613 B |
|
@ -0,0 +1,20 @@
|
||||||
|
# Switcher
|
||||||
|
|
||||||
|
Nice looking radio buttons group.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="switcher">
|
||||||
|
<input class="switcher__input" id="type_first" type="radio" name="type" value="first" checked="checked">
|
||||||
|
<label class="switcher__label" for="type_first">First</label>
|
||||||
|
<input class="switcher__input" id="type_second" type="radio" name="type" value="second">
|
||||||
|
<label class="switcher__label" for="type_second">Second</label>
|
||||||
|
<input class="switcher__input" id="type_third" type="radio" name="type" value="third">
|
||||||
|
<label class="switcher__label" for="type_third">Third</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Skin
|
||||||
|
|
||||||
|
Set `switcher_default_skin` or `modules_default_skin` to `true` to enable default skin.
|
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="switcher">
|
||||||
|
<input class="switcher__input" id="type_first" type="radio" name="type" value="first" checked="checked">
|
||||||
|
<label class="switcher__label" for="type_first">Dog</label>
|
||||||
|
<input class="switcher__input" id="type_second" type="radio" name="type" value="second">
|
||||||
|
<label class="switcher__label" for="type_second">Cat</label>
|
||||||
|
<input class="switcher__input" id="type_third" type="radio" name="type" value="third">
|
||||||
|
<label class="switcher__label" for="type_third">Hamster</label>
|
||||||
|
</div>
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Switcher
|
||||||
|
// Dependencies: form
|
||||||
|
|
||||||
|
// Bones
|
||||||
|
|
||||||
|
.switcher
|
||||||
|
clearfix()
|
||||||
|
no-select()
|
||||||
|
|
||||||
|
&__label,
|
||||||
|
&__input
|
||||||
|
// For prehistoric browsers
|
||||||
|
vertical-align: text-bottom
|
||||||
|
padding-right: .5em
|
||||||
|
font-size: 1em
|
||||||
|
|
||||||
|
&__input:checked,
|
||||||
|
&__input:not(:checked)
|
||||||
|
position: absolute
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
&__input:checked + &__label,
|
||||||
|
&__input:not(:checked) + &__label
|
||||||
|
position: relative
|
||||||
|
float: left
|
||||||
|
box-sizing: border-box
|
||||||
|
vertical-align: top
|
||||||
|
cursor: pointer
|
||||||
|
z-index: 1
|
||||||
|
margin-left: -1px
|
||||||
|
user-select: none
|
||||||
|
|
||||||
|
&__label:nth-of-type(1)
|
||||||
|
margin-left: 0
|
||||||
|
|
||||||
|
&__input:checked + &__label
|
||||||
|
cursor: default
|
||||||
|
z-index: 2
|
||||||
|
|
||||||
|
&.is-disabled
|
||||||
|
opacity: .4
|
||||||
|
|
||||||
|
|
||||||
|
// Default skin
|
||||||
|
|
||||||
|
modules_default_skin ?= true
|
||||||
|
switcher_default_skin ?= false
|
||||||
|
|
||||||
|
if modules_default_skin or switcher_default_skin
|
||||||
|
.switcher
|
||||||
|
&__input:checked + &__label,
|
||||||
|
&__input:not(:checked) + &__label
|
||||||
|
height: 2em
|
||||||
|
padding: .5em 1em
|
||||||
|
background: #f4f4f4
|
||||||
|
background: linear-gradient(to bottom, #fefefe, #f4f4f4)
|
||||||
|
border: 1px solid #bbb
|
||||||
|
line-height: 1
|
||||||
|
color: #555
|
||||||
|
transition: border-color .1s ease-in-out, box-shadow .1s ease-in-out
|
||||||
|
|
||||||
|
&__label:nth-of-type(1)
|
||||||
|
border-radius: form_border_radius 0 0 form_border_radius
|
||||||
|
&__label:nth-last-of-type(1)
|
||||||
|
border-radius: 0 form_border_radius form_border_radius 0
|
||||||
|
|
||||||
|
&__input:checked + &__label
|
||||||
|
background: #ccc
|
||||||
|
background: linear-gradient(to bottom, #bbb, #eee)
|
||||||
|
border-color: #999
|
||||||
|
box-shadow: inset 0 .1em .2em black(.2)
|
||||||
|
text-shadow: 0 1px 0 black(.1)
|
||||||
|
|
||||||
|
&__input:focus + &__label
|
||||||
|
border-color: form_focus_color
|
||||||
|
box-shadow: 0 0 .4em rgba(form_focus_color, .75)
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Basic text styles
|
||||||
|
|
||||||
|
Headings, paragraphs, etc.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="text">
|
||||||
|
<h1>Down the Rabbit-Hole</h1>
|
||||||
|
<p>Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice “without pictures or conversation?”</p>
|
||||||
|
<p>So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.</p>
|
||||||
|
</div>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="text">
|
||||||
|
<h1 class="fixie"></h1>
|
||||||
|
<p class="fixie"></p>
|
||||||
|
<p class="fixie"></p>
|
||||||
|
<h2 class="fixie"></h2>
|
||||||
|
<p class="fixie"></p>
|
||||||
|
</div>
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Basic text styles
|
||||||
|
|
||||||
|
.text
|
||||||
|
hyphens: auto
|
||||||
|
|
||||||
|
p,
|
||||||
|
ul,
|
||||||
|
ol,
|
||||||
|
li,
|
||||||
|
pre
|
||||||
|
margin-bottom: 2*spacer
|
||||||
|
|
||||||
|
.alpha,
|
||||||
|
.text h1,
|
||||||
|
.beta,
|
||||||
|
.text h2,
|
||||||
|
.gamma,
|
||||||
|
.text h3,
|
||||||
|
.delta,
|
||||||
|
.text h4,
|
||||||
|
.epsilon,
|
||||||
|
.text h5
|
||||||
|
margin-top: 3*spacer
|
||||||
|
margin-bottom: spacer
|
||||||
|
line-height: 1.2
|
||||||
|
font-weight: normal
|
||||||
|
|
||||||
|
.alpha,
|
||||||
|
.text h1
|
||||||
|
font-size: 44px
|
||||||
|
|
||||||
|
.beta,
|
||||||
|
.text h2
|
||||||
|
font-size: 34px
|
||||||
|
|
||||||
|
.gamma,
|
||||||
|
.text h3
|
||||||
|
font-size: 28px
|
||||||
|
|
||||||
|
.delta,
|
||||||
|
.text h4
|
||||||
|
font-size: 20px
|
||||||
|
|
||||||
|
.epsilon,
|
||||||
|
.text h5
|
||||||
|
font-size: 1em
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
|
// Collapse margin between headings and before first heading.
|
||||||
|
.text h1 + h2,
|
||||||
|
.text h2 + h3,
|
||||||
|
.text h3 + h4,
|
||||||
|
.text h4 + h5,
|
||||||
|
.alpha + .beta,
|
||||||
|
.beta + .gamma,
|
||||||
|
.gamma + .delta,
|
||||||
|
.delta + .epsilon,
|
||||||
|
h1:first-child,
|
||||||
|
h2:first-child,
|
||||||
|
h3:first-child,
|
||||||
|
h4:first-child,
|
||||||
|
h5:first-child,
|
||||||
|
.alpha:first-child,
|
||||||
|
.beta:first-child,
|
||||||
|
.gamma:first-child,
|
||||||
|
.delta:first-child
|
||||||
|
margin-top: 0
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Tooltip
|
||||||
|
|
||||||
|
Simple tooltips.
|
||||||
|
|
||||||
|
|
||||||
|
## Markup
|
||||||
|
|
||||||
|
<div class="tooltip">I’m tooltip!</div>
|
||||||
|
|
||||||
|
<a href="#" class="has-tooltip" data-tooltip="Call us!">+7 495 212-85-06</a>
|
||||||
|
|
||||||
|
|
||||||
|
## Skin
|
||||||
|
|
||||||
|
Set `tooltip_default_skin` or `modules_default_skin` to `true` to enable default skin.
|
|
@ -0,0 +1 @@
|
||||||
|
<span class="has-tooltip" data-tooltip="Call us!">+7 495 212-85-06</span>
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Tooltip
|
||||||
|
|
||||||
|
// Bones
|
||||||
|
|
||||||
|
.tooltip,
|
||||||
|
.has-tooltip:before
|
||||||
|
position: relative
|
||||||
|
display: inline-block
|
||||||
|
text-decoration: none
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
|
.tooltip:after,
|
||||||
|
.has-tooltip:before,
|
||||||
|
.has-tooltip:after
|
||||||
|
content: ""
|
||||||
|
position: absolute
|
||||||
|
left: 50%
|
||||||
|
transform: translateX(-50%)
|
||||||
|
|
||||||
|
.has-tooltip
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
&:before
|
||||||
|
content: attr(data-tooltip);
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after
|
||||||
|
top: 100%
|
||||||
|
display: none
|
||||||
|
|
||||||
|
&:hover:before,
|
||||||
|
&:hover:after
|
||||||
|
display: block
|
||||||
|
|
||||||
|
|
||||||
|
// Default skin
|
||||||
|
|
||||||
|
modules_default_skin ?= true
|
||||||
|
tooltip_default_skin ?= false
|
||||||
|
|
||||||
|
if modules_default_skin or tooltip_default_skin
|
||||||
|
|
||||||
|
_tooltip_arrow = 5px
|
||||||
|
_tooltip_bg = black(0.9)
|
||||||
|
|
||||||
|
.tooltip,
|
||||||
|
.has-tooltip:before
|
||||||
|
padding: .2em .5em
|
||||||
|
background: _tooltip_bg
|
||||||
|
color: #fff
|
||||||
|
font-size: 14px
|
||||||
|
border-radius: form_border_radius
|
||||||
|
|
||||||
|
.tooltip:after,
|
||||||
|
.has-tooltip:after
|
||||||
|
triangle("up", _tooltip_arrow, _tooltip_bg)
|
||||||
|
|
||||||
|
.tooltip:after
|
||||||
|
top: (-(_tooltip_arrow))
|
||||||
|
|
||||||
|
.has-tooltip:before
|
||||||
|
margin-top: _tooltip_arrow
|
|
@ -0,0 +1,138 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Base CSS
|
||||||
|
|
||||||
|
// Global reset.
|
||||||
|
*
|
||||||
|
padding: 0
|
||||||
|
margin: 0
|
||||||
|
box-sizing: border-box
|
||||||
|
article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary
|
||||||
|
display: block
|
||||||
|
sup, sub, small, code
|
||||||
|
line-height: 0
|
||||||
|
img
|
||||||
|
max-width: 100%
|
||||||
|
height: auto
|
||||||
|
img
|
||||||
|
vertical-align: middle
|
||||||
|
a img, a.img
|
||||||
|
border: none !important
|
||||||
|
background-image: none !important
|
||||||
|
abbr
|
||||||
|
border-bottom: none
|
||||||
|
ul
|
||||||
|
list-style: none
|
||||||
|
table
|
||||||
|
border-collapse: collapse
|
||||||
|
border-spacing: 0
|
||||||
|
|
||||||
|
html
|
||||||
|
// Force scrollbar in non IE
|
||||||
|
overflow-y: scroll
|
||||||
|
// Prevent iOS text size adjust on device orientation change, without disabling user zoom: h5bp.com/g
|
||||||
|
-webkit-text-size-adjust: 100%
|
||||||
|
-ms-text-size-adjust: 100%
|
||||||
|
if sticky_footer_height
|
||||||
|
position: relative
|
||||||
|
min-height: 100%
|
||||||
|
|
||||||
|
// Sticky footer: mystrd.at/modern-clean-css-sticky-footer/.
|
||||||
|
if sticky_footer_height
|
||||||
|
body
|
||||||
|
padding-bottom: sticky_footer_height
|
||||||
|
.footer
|
||||||
|
sticky-footer(sticky_footer_height)
|
||||||
|
padding: 0 spacer
|
||||||
|
if max_width
|
||||||
|
&-i
|
||||||
|
max-width: max_width
|
||||||
|
margin-left: auto
|
||||||
|
margin-right: auto
|
||||||
|
|
||||||
|
// www.aestheticallyloyal.com/public/optimize-legibility/
|
||||||
|
h1, h2, h3
|
||||||
|
text-rendering: optimizeLegibility
|
||||||
|
|
||||||
|
// Hand cursor on clickable input elements
|
||||||
|
input[type="button"],
|
||||||
|
input[type="submit"],
|
||||||
|
input[type="image"],
|
||||||
|
button
|
||||||
|
cursor: pointer
|
||||||
|
button[disabled],
|
||||||
|
input[disabled]
|
||||||
|
cursor: default
|
||||||
|
|
||||||
|
// Forms: github.com/necolas/normalize.css/blob/master/normalize.css.
|
||||||
|
button,
|
||||||
|
input
|
||||||
|
line-height: normal
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea
|
||||||
|
font-family: inherit
|
||||||
|
font-size: 100%
|
||||||
|
button,
|
||||||
|
input[type="button"],
|
||||||
|
input[type="reset"],
|
||||||
|
input[type="submit"]
|
||||||
|
-webkit-appearance: button
|
||||||
|
input[type="search"]
|
||||||
|
-webkit-appearance: textfield
|
||||||
|
input[type="search"]::-webkit-search-decoration,
|
||||||
|
input[type="search"]::-webkit-search-cancel-button
|
||||||
|
-webkit-appearance: none
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
input::-moz-focus-inner
|
||||||
|
border: 0
|
||||||
|
textarea
|
||||||
|
overflow: auto
|
||||||
|
vertical-align: top
|
||||||
|
resize: vertical
|
||||||
|
fieldset,
|
||||||
|
legend
|
||||||
|
border: 0
|
||||||
|
[hidden]
|
||||||
|
display: none
|
||||||
|
|
||||||
|
// Pre with wrapping.
|
||||||
|
pre
|
||||||
|
white-space: pre-wrap
|
||||||
|
|
||||||
|
// Addresses outline inconsistency between Chrome and other browsers.
|
||||||
|
a:focus
|
||||||
|
outline: thin dotted
|
||||||
|
|
||||||
|
// Improve readability when focused and also mouse hovered in all browsers.
|
||||||
|
a:hover,
|
||||||
|
a:active
|
||||||
|
outline: 0
|
||||||
|
|
||||||
|
// Text selection and iOS tap highlighting.
|
||||||
|
if light(bg_color)
|
||||||
|
_selection_color = rgba(darken(bg_color,60),.5)
|
||||||
|
else
|
||||||
|
_selection_color = rgba(lighten(bg_color,60),.5)
|
||||||
|
text-selection(base_color, _selection_color)
|
||||||
|
a:link
|
||||||
|
-webkit-tap-highlight-color: rgba(_selection_color,.25)
|
||||||
|
|
||||||
|
// Hide phone links from desktop browsers.
|
||||||
|
.no-touch a[href^="tel"]
|
||||||
|
&:link,
|
||||||
|
&:visited,
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus
|
||||||
|
position: inherit
|
||||||
|
text-decoration: inherit
|
||||||
|
border: inherit
|
||||||
|
color: inherit
|
||||||
|
background-image: none
|
||||||
|
cursor: default
|
||||||
|
|
||||||
|
if content_max_width
|
||||||
|
.content
|
||||||
|
max-width: content_max_width
|
||||||
|
margin: 0 auto
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Helper classes
|
||||||
|
|
||||||
|
// Element is hidden.
|
||||||
|
.is-hidden
|
||||||
|
display: none
|
||||||
|
|
||||||
|
// Element is invisible (but occupies place on page).
|
||||||
|
.is-invisible
|
||||||
|
visibility: hidden
|
||||||
|
|
||||||
|
/// Element is in transit between hidden (.is-hidden) and visible.
|
||||||
|
.is-transit
|
||||||
|
display: block
|
||||||
|
&.l-center
|
||||||
|
display: table
|
||||||
|
|
||||||
|
// Clearfix.
|
||||||
|
.group
|
||||||
|
clearfix()
|
|
@ -0,0 +1,215 @@
|
||||||
|
# Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
# https://github.com/sapegin/tamia
|
||||||
|
# JS component base class
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
$ = jQuery
|
||||||
|
|
||||||
|
###
|
||||||
|
JS component base class.
|
||||||
|
|
||||||
|
Elements: any HTML element with class name that follow a pattern `.js-name` where `name` is an element name.
|
||||||
|
|
||||||
|
States: any class on component root HTML node that follow a pattern `.is-state` where `state` is a state name.
|
||||||
|
After initialization all components will have `ok` state.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
class Pony extends Component
|
||||||
|
init: ->
|
||||||
|
@on('click', 'toggle', @toggle)
|
||||||
|
toggle: ->
|
||||||
|
@toggleState('pink')
|
||||||
|
|
||||||
|
tamia.initComponents(pony: Pony)
|
||||||
|
|
||||||
|
<div class="pink-pony is-pink" data-component="pony">
|
||||||
|
<button class="pink-pony__button js-toggle">To pink or not to pink?</div>
|
||||||
|
</div>
|
||||||
|
###
|
||||||
|
class Component
|
||||||
|
constructor: (elem) ->
|
||||||
|
if not elem or elem.nodeType isnt 1 then throw new ReferenceError('No DOM node passed to Component constructor.')
|
||||||
|
|
||||||
|
@elemNode = elem
|
||||||
|
@elem = $(elem)
|
||||||
|
@initializable = @isInitializable()
|
||||||
|
if not @initializable
|
||||||
|
return
|
||||||
|
@_fillStates()
|
||||||
|
if @isSupported()
|
||||||
|
@handlers = {}
|
||||||
|
@init()
|
||||||
|
@addState('ok')
|
||||||
|
else
|
||||||
|
@fallback()
|
||||||
|
@addState('unsupported')
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
Put all your initialization code in this method.
|
||||||
|
###
|
||||||
|
init: ->
|
||||||
|
# Should be implemented
|
||||||
|
|
||||||
|
###
|
||||||
|
You can implement this method to do destroy component.
|
||||||
|
###
|
||||||
|
destroy: ->
|
||||||
|
# Could be implemented
|
||||||
|
|
||||||
|
###
|
||||||
|
Implement this method if you want to check whether browser is good for your component or not.
|
||||||
|
|
||||||
|
@returns {Boolean}
|
||||||
|
###
|
||||||
|
isSupported: ->
|
||||||
|
return true
|
||||||
|
|
||||||
|
###
|
||||||
|
Implement this method if you want to check whether component could be initialized.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
isInitializable: ->
|
||||||
|
# Do not initialize component if it's not visible
|
||||||
|
@isVisible()
|
||||||
|
|
||||||
|
@return {Boolean}
|
||||||
|
###
|
||||||
|
isInitializable: ->
|
||||||
|
return true
|
||||||
|
|
||||||
|
###
|
||||||
|
You can implement this method to do some fallbacks. It will be called if isSupported() returns false.
|
||||||
|
###
|
||||||
|
fallback: ->
|
||||||
|
# Could be implemented
|
||||||
|
|
||||||
|
###
|
||||||
|
Finds element.
|
||||||
|
|
||||||
|
@param {String} name Element ID.
|
||||||
|
|
||||||
|
@return {jQuery} Element with .js-name class.
|
||||||
|
###
|
||||||
|
find: (name) ->
|
||||||
|
return @elem.find(".js-#{name}").first()
|
||||||
|
|
||||||
|
###
|
||||||
|
Attaches event handler.
|
||||||
|
|
||||||
|
@param {String} events Event names (space separated).
|
||||||
|
@param {String} [element] Element id.
|
||||||
|
@param {Function} handler Handler function (scope will automatically sets to this).
|
||||||
|
###
|
||||||
|
on: (args...) ->
|
||||||
|
@_toggleEvent('on', args...)
|
||||||
|
|
||||||
|
###
|
||||||
|
Detaches event handler.
|
||||||
|
|
||||||
|
@param {String} events Event names (space separated).
|
||||||
|
@param {String} [element] Element id.
|
||||||
|
@param {Function} handler Handler function (scope will automatically sets to this).
|
||||||
|
###
|
||||||
|
off: (args...) ->
|
||||||
|
@_toggleEvent('off', args...)
|
||||||
|
|
||||||
|
###
|
||||||
|
Returns component state.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
|
||||||
|
@return {Boolean} Sate value.
|
||||||
|
###
|
||||||
|
hasState: (name) ->
|
||||||
|
return !!@states[name]
|
||||||
|
|
||||||
|
###
|
||||||
|
Sets state to true.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
###
|
||||||
|
addState: (name) ->
|
||||||
|
@toggleState(name, true)
|
||||||
|
|
||||||
|
###
|
||||||
|
Sets state to false.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
###
|
||||||
|
removeState: (name) ->
|
||||||
|
@toggleState(name, false)
|
||||||
|
|
||||||
|
###
|
||||||
|
Toggles state value.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
@param {Boolean} [value] State value.
|
||||||
|
###
|
||||||
|
toggleState: (name, value = not @states[name]) ->
|
||||||
|
@states[name] = value
|
||||||
|
@_updateStates()
|
||||||
|
|
||||||
|
###
|
||||||
|
Returns component visibility.
|
||||||
|
|
||||||
|
@return {Boolean}
|
||||||
|
###
|
||||||
|
isVisible: ->
|
||||||
|
return !!(@elemNode.offsetWidth or @elemNode.offsetHeight)
|
||||||
|
|
||||||
|
_toggleEvent: (action, args...) ->
|
||||||
|
if typeof args[1] is 'string'
|
||||||
|
# Selector passed
|
||||||
|
args[1] = ".js-#{args[1]}"
|
||||||
|
|
||||||
|
# Bind handler to this
|
||||||
|
funcArg = args.length - 1 # Last argument
|
||||||
|
func = args[funcArg]
|
||||||
|
handler
|
||||||
|
if @handlers[func]
|
||||||
|
handler = @handlers[func]
|
||||||
|
if action is 'on'
|
||||||
|
if handler
|
||||||
|
handler.counter++
|
||||||
|
else
|
||||||
|
@handlers[func] = handler =
|
||||||
|
counter: 1
|
||||||
|
func: func.bind(this)
|
||||||
|
return if not handler
|
||||||
|
args[funcArg] = handler.func
|
||||||
|
|
||||||
|
# Pass to jQuery
|
||||||
|
@elem[action](args...)
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
if action is 'off'
|
||||||
|
handler.counter--
|
||||||
|
if handler.counter <= 0
|
||||||
|
@handlers[func] = null
|
||||||
|
|
||||||
|
_fillStates: ->
|
||||||
|
states = {}
|
||||||
|
classes = @elemNode.className.split(' ')
|
||||||
|
for clsName of classes
|
||||||
|
cls = classes[clsName]
|
||||||
|
re = /^is-/
|
||||||
|
if re.test(cls)
|
||||||
|
states[cls.replace(re, '')] = true
|
||||||
|
@states = states
|
||||||
|
|
||||||
|
_updateStates: ->
|
||||||
|
classes = @elemNode.className
|
||||||
|
classes = $.trim(classes.replace(/\bis-[-\w]+/g, ''))
|
||||||
|
classes = classes.split(/\s+/)
|
||||||
|
for name of @states
|
||||||
|
if @states[name]
|
||||||
|
classes.push("is-#{name}")
|
||||||
|
@elemNode.className = classes.join(' ')
|
||||||
|
|
||||||
|
Component.__tamia_cmpnt__ = true
|
||||||
|
|
||||||
|
window.Component = Component
|
|
@ -0,0 +1,278 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var $, Component,
|
||||||
|
__slice = [].slice;
|
||||||
|
|
||||||
|
$ = jQuery;
|
||||||
|
|
||||||
|
/*
|
||||||
|
JS component base class.
|
||||||
|
|
||||||
|
Elements: any HTML element with class name that follow a pattern `.js-name` where `name` is an element name.
|
||||||
|
|
||||||
|
States: any class on component root HTML node that follow a pattern `.is-state` where `state` is a state name.
|
||||||
|
After initialization all components will have `ok` state.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
class Pony extends Component
|
||||||
|
init: ->
|
||||||
|
@on('click', 'toggle', @toggle)
|
||||||
|
toggle: ->
|
||||||
|
@toggleState('pink')
|
||||||
|
|
||||||
|
tamia.initComponents(pony: Pony)
|
||||||
|
|
||||||
|
<div class="pink-pony is-pink" data-component="pony">
|
||||||
|
<button class="pink-pony__button js-toggle">To pink or not to pink?</div>
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component = (function() {
|
||||||
|
function Component(elem) {
|
||||||
|
if (!elem || elem.nodeType !== 1) {
|
||||||
|
throw new ReferenceError('No DOM node passed to Component constructor.');
|
||||||
|
}
|
||||||
|
this.elemNode = elem;
|
||||||
|
this.elem = $(elem);
|
||||||
|
this.initializable = this.isInitializable();
|
||||||
|
if (!this.initializable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._fillStates();
|
||||||
|
if (this.isSupported()) {
|
||||||
|
this.handlers = {};
|
||||||
|
this.init();
|
||||||
|
this.addState('ok');
|
||||||
|
} else {
|
||||||
|
this.fallback();
|
||||||
|
this.addState('unsupported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Put all your initialization code in this method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.init = function() {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
You can implement this method to do destroy component.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.destroy = function() {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Implement this method if you want to check whether browser is good for your component or not.
|
||||||
|
|
||||||
|
@returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.isSupported = function() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Implement this method if you want to check whether component could be initialized.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
isInitializable: ->
|
||||||
|
# Do not initialize component if it's not visible
|
||||||
|
@isVisible()
|
||||||
|
|
||||||
|
@return {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.isInitializable = function() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
You can implement this method to do some fallbacks. It will be called if isSupported() returns false.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.fallback = function() {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finds element.
|
||||||
|
|
||||||
|
@param {String} name Element ID.
|
||||||
|
|
||||||
|
@return {jQuery} Element with .js-name class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.find = function(name) {
|
||||||
|
return this.elem.find(".js-" + name).first();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Attaches event handler.
|
||||||
|
|
||||||
|
@param {String} events Event names (space separated).
|
||||||
|
@param {String} [element] Element id.
|
||||||
|
@param {Function} handler Handler function (scope will automatically sets to this).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.on = function() {
|
||||||
|
var args;
|
||||||
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
||||||
|
return this._toggleEvent.apply(this, ['on'].concat(__slice.call(args)));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Detaches event handler.
|
||||||
|
|
||||||
|
@param {String} events Event names (space separated).
|
||||||
|
@param {String} [element] Element id.
|
||||||
|
@param {Function} handler Handler function (scope will automatically sets to this).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.off = function() {
|
||||||
|
var args;
|
||||||
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
||||||
|
return this._toggleEvent.apply(this, ['off'].concat(__slice.call(args)));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns component state.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
|
||||||
|
@return {Boolean} Sate value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.hasState = function(name) {
|
||||||
|
return !!this.states[name];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sets state to true.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.addState = function(name) {
|
||||||
|
return this.toggleState(name, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sets state to false.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.removeState = function(name) {
|
||||||
|
return this.toggleState(name, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Toggles state value.
|
||||||
|
|
||||||
|
@param {String} [name] State name.
|
||||||
|
@param {Boolean} [value] State value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.toggleState = function(name, value) {
|
||||||
|
if (value == null) {
|
||||||
|
value = !this.states[name];
|
||||||
|
}
|
||||||
|
this.states[name] = value;
|
||||||
|
return this._updateStates();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns component visibility.
|
||||||
|
|
||||||
|
@return {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Component.prototype.isVisible = function() {
|
||||||
|
return !!(this.elemNode.offsetWidth || this.elemNode.offsetHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
Component.prototype._toggleEvent = function() {
|
||||||
|
var action, args, func, funcArg, handler, _ref;
|
||||||
|
action = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||||
|
if (typeof args[1] === 'string') {
|
||||||
|
args[1] = ".js-" + args[1];
|
||||||
|
}
|
||||||
|
funcArg = args.length - 1;
|
||||||
|
func = args[funcArg];
|
||||||
|
handler;
|
||||||
|
if (this.handlers[func]) {
|
||||||
|
handler = this.handlers[func];
|
||||||
|
}
|
||||||
|
if (action === 'on') {
|
||||||
|
if (handler) {
|
||||||
|
handler.counter++;
|
||||||
|
} else {
|
||||||
|
this.handlers[func] = handler = {
|
||||||
|
counter: 1,
|
||||||
|
func: func.bind(this)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!handler) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
args[funcArg] = handler.func;
|
||||||
|
(_ref = this.elem)[action].apply(_ref, args);
|
||||||
|
if (action === 'off') {
|
||||||
|
handler.counter--;
|
||||||
|
if (handler.counter <= 0) {
|
||||||
|
return this.handlers[func] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Component.prototype._fillStates = function() {
|
||||||
|
var classes, cls, clsName, re, states;
|
||||||
|
states = {};
|
||||||
|
classes = this.elemNode.className.split(' ');
|
||||||
|
for (clsName in classes) {
|
||||||
|
cls = classes[clsName];
|
||||||
|
re = /^is-/;
|
||||||
|
if (re.test(cls)) {
|
||||||
|
states[cls.replace(re, '')] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.states = states;
|
||||||
|
};
|
||||||
|
|
||||||
|
Component.prototype._updateStates = function() {
|
||||||
|
var classes, name;
|
||||||
|
classes = this.elemNode.className;
|
||||||
|
classes = $.trim(classes.replace(/\bis-[-\w]+/g, ''));
|
||||||
|
classes = classes.split(/\s+/);
|
||||||
|
for (name in this.states) {
|
||||||
|
if (this.states[name]) {
|
||||||
|
classes.push("is-" + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.elemNode.className = classes.join(' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
return Component;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Component.__tamia_cmpnt__ = true;
|
||||||
|
|
||||||
|
window.Component = Component;
|
||||||
|
|
||||||
|
}).call(this);
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
// White color with transparency.
|
||||||
|
//
|
||||||
|
// opacity - Opacity value (0—1).
|
||||||
|
//
|
||||||
|
// Returns color.
|
||||||
|
white(opacity)
|
||||||
|
rgba(255, 255, 255, opacity)
|
||||||
|
|
||||||
|
// Black color with transparency.
|
||||||
|
//
|
||||||
|
// opacity - Opacity value (0—1).
|
||||||
|
//
|
||||||
|
// Returns color.
|
||||||
|
black(opacity)
|
||||||
|
rgba(0, 0, 0, opacity)
|
|
@ -0,0 +1,147 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Images, sprites, Retina support
|
||||||
|
|
||||||
|
//
|
||||||
|
// Configuration
|
||||||
|
//
|
||||||
|
|
||||||
|
// Enable Retina support (default: false).
|
||||||
|
retinafy ?= false
|
||||||
|
|
||||||
|
// Path to calculate file system image path based on CSS path (default: .).
|
||||||
|
images_relative_root ?= '.'
|
||||||
|
|
||||||
|
// Default sprite image file (default: ../build/sprite.png).
|
||||||
|
sprite_image ?= '../build/sprite.png';
|
||||||
|
sprite_image = sprite_image + '?' + sprite_fingerprint if sprite_fingerprint
|
||||||
|
|
||||||
|
// Sprite step size (default: 20px).
|
||||||
|
sprite_step ?= 20px;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// background-image with Retina variant.
|
||||||
|
//
|
||||||
|
// path - Image file path.
|
||||||
|
// x - background-position x (default: 0).
|
||||||
|
// y - background-position y (default: 0).
|
||||||
|
//
|
||||||
|
// Retina image file should be named path@2x.png.
|
||||||
|
if retinafy
|
||||||
|
image(path, x=0, y=0)
|
||||||
|
background: url(path) x y
|
||||||
|
+retina()
|
||||||
|
ext = extname(path)
|
||||||
|
hdpath = dirname(path) + '/' + basename(path, ext) + '@2x' + ext
|
||||||
|
background: url(hdpath) x y
|
||||||
|
background-size: image-size(pathjoin(images_relative_root, path))
|
||||||
|
else
|
||||||
|
image(path, x=0, y=0)
|
||||||
|
background: url(path) x y
|
||||||
|
|
||||||
|
|
||||||
|
// Sprite (to use in pseudo element).
|
||||||
|
//
|
||||||
|
// Sprite generated by grunt-squirrelsprite:
|
||||||
|
// img - Sprite image variable.
|
||||||
|
//
|
||||||
|
// Manually created sprite:
|
||||||
|
// x - Horizontal position in sprite grid.
|
||||||
|
// y - Vertical position in sprite grid.
|
||||||
|
// w - Sprite width, pixels.
|
||||||
|
// h - sprite height, pixels.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// .elem
|
||||||
|
// sprite(sprite_pony);
|
||||||
|
//
|
||||||
|
// .elem2
|
||||||
|
// sprite(5, 6, 36, 22);
|
||||||
|
sprite(img)
|
||||||
|
if not @content and match(":(before|after)", selector())
|
||||||
|
content: ""
|
||||||
|
if not @display
|
||||||
|
display: inline-block
|
||||||
|
if length(img) > 1
|
||||||
|
image(sprite_image, img[0], img[1])
|
||||||
|
width: img[2]
|
||||||
|
height: img[3]
|
||||||
|
else
|
||||||
|
image(sprite_image, sprite-x(arguments[0]), sprite-y(arguments[1]))
|
||||||
|
width: arguments[2]
|
||||||
|
height: arguments[3]
|
||||||
|
|
||||||
|
// Horizontal position of sprite image.
|
||||||
|
//
|
||||||
|
// x - Horizontal position in sprite grid.
|
||||||
|
//
|
||||||
|
// Returns pixels.
|
||||||
|
sprite-x(x)
|
||||||
|
(-((x - 1)*sprite_step+1));
|
||||||
|
|
||||||
|
// Vertical position of sprite image.
|
||||||
|
//
|
||||||
|
// y - Vertical position in sprite grid.
|
||||||
|
//
|
||||||
|
// Returns pixels.
|
||||||
|
sprite-y(y)
|
||||||
|
(-((y - 1)*sprite_step+1));
|
||||||
|
|
||||||
|
// background-position for sprite.
|
||||||
|
//
|
||||||
|
// x - Horizontal position in sprite grid.
|
||||||
|
// y - Vertical position in sprite grid.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// .elem
|
||||||
|
// sprite-bg()
|
||||||
|
// sprite-pos(5,6)
|
||||||
|
// sprite-pos(sprite_pony-hover)
|
||||||
|
sprite-pos(img)
|
||||||
|
if length(img) > 1
|
||||||
|
background-position: img[0] img[1]
|
||||||
|
else
|
||||||
|
background-position: sprite-x(img[0]) sprite-y(img[1])
|
||||||
|
|
||||||
|
// background-image for sprite.
|
||||||
|
//
|
||||||
|
// Sprite generated by grunt-squirrelsprite:
|
||||||
|
// img - Sprite image variable.
|
||||||
|
//
|
||||||
|
// Manually created sprite:
|
||||||
|
// x - Horizontal position in sprite grid (default: 0).
|
||||||
|
// y - Vertical position in sprite grid (default: 0).
|
||||||
|
sprite-bg(x=0, y=0)
|
||||||
|
image(sprite_image, x, x)
|
||||||
|
|
||||||
|
// Element width for sprite.
|
||||||
|
//
|
||||||
|
// Returns pixels
|
||||||
|
sprite-width(img)
|
||||||
|
img[2]
|
||||||
|
|
||||||
|
// Element height for sprite.
|
||||||
|
//
|
||||||
|
// Returns pixels
|
||||||
|
sprite-height(img)
|
||||||
|
img[3]
|
||||||
|
|
||||||
|
// Element width/height for sprite.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// .elem
|
||||||
|
// sprite-size(sprite_pony);
|
||||||
|
sprite-size(img)
|
||||||
|
width: sprite-width(img)
|
||||||
|
height: sprite-height(img)
|
||||||
|
|
||||||
|
// Shifts element half height to top
|
||||||
|
//
|
||||||
|
sprite-shift-top(img)
|
||||||
|
margin-top: (-(round(sprite-height(img)/2)))
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Configuration
|
||||||
|
|
||||||
|
/// Debug mode.
|
||||||
|
DEBUG ?= false
|
||||||
|
|
||||||
|
// Default spacer (default: 10px).
|
||||||
|
spacer ?= 10px;
|
||||||
|
|
||||||
|
// Max page with.
|
||||||
|
max_width ?= null;
|
||||||
|
|
||||||
|
// Max content block (.content) with.
|
||||||
|
content_max_width ?= null;
|
||||||
|
|
||||||
|
// Sticky footer height (default: no sticky footer).
|
||||||
|
sticky_footer_height ?= null;
|
||||||
|
|
||||||
|
// Background color (default: white).
|
||||||
|
bg_color ?= #fff;
|
||||||
|
|
||||||
|
// Base text color (default: #111).
|
||||||
|
base_color ?= #111;
|
||||||
|
|
||||||
|
// Form focus outline color (default: hsl(204,68%,69%)).
|
||||||
|
form_focus_color ?= hsl(204, 68%, 69%)
|
||||||
|
|
||||||
|
// Form border radius (default: .15em).
|
||||||
|
form_border_radius ?= .15em
|
||||||
|
|
||||||
|
|
||||||
|
@import "./misc"
|
||||||
|
@import "./functions"
|
||||||
|
@import "./layout"
|
||||||
|
@import "./mediaqueries"
|
||||||
|
@import "./images"
|
||||||
|
@import "./bootstrap"
|
||||||
|
@import "./classes"
|
||||||
|
@import "./links"
|
|
@ -0,0 +1,295 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Grids and layouts
|
||||||
|
|
||||||
|
//
|
||||||
|
// Configuration
|
||||||
|
//
|
||||||
|
|
||||||
|
// Grid gutter size, in pixels (default: 2×spacer).
|
||||||
|
grid_gutter ?= 2*spacer
|
||||||
|
|
||||||
|
// Number of columns in grid (default: 12).
|
||||||
|
grid_columns ?= 12
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Grid
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Inspired by http://zengrids.com
|
||||||
|
|
||||||
|
// Columns wrapper.
|
||||||
|
grid-row()
|
||||||
|
clearfix()
|
||||||
|
grid-wrapper()
|
||||||
|
|
||||||
|
// Column (grid).
|
||||||
|
//
|
||||||
|
// position - Start column number (default: 1).
|
||||||
|
// span - Width, in culumns (default: 1).
|
||||||
|
// context - Width of parent column (default: null).
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// .row>.col1+.col2
|
||||||
|
//
|
||||||
|
// .row
|
||||||
|
// grid-row()
|
||||||
|
// .col1
|
||||||
|
// grid-col(1,2)
|
||||||
|
// .col2
|
||||||
|
// grid-col(3,10)
|
||||||
|
grid-col(position=1, span=1, context=null)
|
||||||
|
_grid-column(position, span, context)
|
||||||
|
_grid-float()
|
||||||
|
grid-padding()
|
||||||
|
|
||||||
|
// Single column.
|
||||||
|
//
|
||||||
|
// position - Start column number (default: 1).
|
||||||
|
// span - Width, in culumns (default: 1).
|
||||||
|
// context - Width of parent column (default: null).
|
||||||
|
grid-one(position=1, span=1, context=null)
|
||||||
|
_grid-column(position, span, context)
|
||||||
|
grid-padding()
|
||||||
|
|
||||||
|
// Single column (without padding, wrapper for child columns).
|
||||||
|
//
|
||||||
|
// position - Start column number (default: 1).
|
||||||
|
// span - Width, in culumns (default: 1).
|
||||||
|
// context - Width of parent column (default: null).
|
||||||
|
grid-one-container(position=1, span=1, context=null)
|
||||||
|
clearfix()
|
||||||
|
_grid-column(position, span, context)
|
||||||
|
|
||||||
|
// Gutter size negative margin to make column with different background.
|
||||||
|
// You should adjust padding depending on content.
|
||||||
|
grid-explode()
|
||||||
|
margin: (-(grid_gutter))
|
||||||
|
|
||||||
|
// Width of column, in percent.
|
||||||
|
//
|
||||||
|
// position - Start column number (default: 1).
|
||||||
|
// span - Width, in culumns (default: 1).
|
||||||
|
//
|
||||||
|
// Returns percent.
|
||||||
|
grid-width(span=1, context=null)
|
||||||
|
context = grid_columns if not context
|
||||||
|
unit-width = 100% / context
|
||||||
|
span * unit-width
|
||||||
|
|
||||||
|
// Column left/right padding.
|
||||||
|
//
|
||||||
|
// full - Padding on all sides if true, left/right otherwise (default: false).
|
||||||
|
grid-padding(full=false)
|
||||||
|
side-gutter = grid_gutter / 2;
|
||||||
|
if full
|
||||||
|
padding: side-gutter
|
||||||
|
else
|
||||||
|
padding-left: side-gutter
|
||||||
|
padding-right: side-gutter
|
||||||
|
|
||||||
|
// Column wrapper left/right negative margin.
|
||||||
|
grid-wrapper()
|
||||||
|
side-gutter = (-(grid_gutter / 2))
|
||||||
|
margin-left: side-gutter
|
||||||
|
margin-right: side-gutter
|
||||||
|
|
||||||
|
_grid-column(position=1, span=1, context=null)
|
||||||
|
context = grid_columns if not context
|
||||||
|
unit-width = 100% / context
|
||||||
|
width: span * unit-width
|
||||||
|
margin-left: (position - 1) * unit-width
|
||||||
|
|
||||||
|
_grid-float()
|
||||||
|
float: left
|
||||||
|
margin-right: -100%
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Layouts
|
||||||
|
//
|
||||||
|
|
||||||
|
// Layout wrapper.
|
||||||
|
layout-row()
|
||||||
|
grid-wrapper()
|
||||||
|
display: flex
|
||||||
|
flex-flow: row wrap
|
||||||
|
// flex-direction: row
|
||||||
|
/// IE8-9
|
||||||
|
.no-flexbox &
|
||||||
|
letter-spacing: -0.31em
|
||||||
|
|
||||||
|
// Column (simple layout).
|
||||||
|
//
|
||||||
|
// part - 1/Nth part of wrapper.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// .row>.col+.col
|
||||||
|
//
|
||||||
|
// .row
|
||||||
|
// layout-row()
|
||||||
|
// .col
|
||||||
|
// layout-nth(2) // Half
|
||||||
|
layout-nth(part)
|
||||||
|
_layout-col()
|
||||||
|
_layout-part(part)
|
||||||
|
|
||||||
|
// Change number of columns.
|
||||||
|
//
|
||||||
|
// Use it to change number of columns (defined via layout-nth()) inside media queries.
|
||||||
|
//
|
||||||
|
// part - 1/Nth part of wrapper.
|
||||||
|
layout-change(part)
|
||||||
|
_layout-part(part)
|
||||||
|
|
||||||
|
// Disable columns.
|
||||||
|
//
|
||||||
|
// Alias for layout-change(1).
|
||||||
|
layout-stop()
|
||||||
|
_layout-part(1)
|
||||||
|
|
||||||
|
|
||||||
|
// Center element with specified width and hegith.
|
||||||
|
center(width, height=null)
|
||||||
|
size(width, height)
|
||||||
|
left: 50%
|
||||||
|
top: 50%
|
||||||
|
margin-left: (-(@width / 2))
|
||||||
|
margin-top: (-(@height / 2))
|
||||||
|
|
||||||
|
_layout-col()
|
||||||
|
grid-padding()
|
||||||
|
// IE8-9
|
||||||
|
.no-flexbox &
|
||||||
|
display: inline-block
|
||||||
|
vertical-align: top
|
||||||
|
letter-spacing: normal
|
||||||
|
|
||||||
|
_layout-part(part)
|
||||||
|
width: (100% / part)
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Classes
|
||||||
|
//
|
||||||
|
|
||||||
|
// Column wrapper.
|
||||||
|
.l-row
|
||||||
|
layout-row()
|
||||||
|
|
||||||
|
.l-sixth,
|
||||||
|
.l-quarter,
|
||||||
|
.l-third,
|
||||||
|
.l-half,
|
||||||
|
.l-three-quarters,
|
||||||
|
.l-two-thirds
|
||||||
|
_layout-col()
|
||||||
|
|
||||||
|
// Sixth (to use inside .l-row).
|
||||||
|
.l-sixth
|
||||||
|
_layout-part(6)
|
||||||
|
|
||||||
|
// Quarter (to use inside .l-row).
|
||||||
|
.l-quarter
|
||||||
|
_layout-part(4)
|
||||||
|
|
||||||
|
// Three quarters (to use inside .l-row).
|
||||||
|
.l-three-quarters
|
||||||
|
_layout-part(4/3)
|
||||||
|
|
||||||
|
// Third (to use inside .l-row).
|
||||||
|
.l-third
|
||||||
|
_layout-part(3)
|
||||||
|
|
||||||
|
// Two thirds (to use inside .l-row).
|
||||||
|
.l-two-thirds
|
||||||
|
_layout-part(3/2)
|
||||||
|
|
||||||
|
// Half (to use inside .l-row).
|
||||||
|
.l-half
|
||||||
|
_layout-part(2)
|
||||||
|
|
||||||
|
// Flexible columns with left (.l-left) and right (.l-right) text alignment (to use inside .l-row).
|
||||||
|
.l-left,
|
||||||
|
.l-right
|
||||||
|
flex: 1
|
||||||
|
.l-right
|
||||||
|
text-align: right
|
||||||
|
.no-flexbox
|
||||||
|
.l-left
|
||||||
|
float: left
|
||||||
|
.l-right
|
||||||
|
float: right
|
||||||
|
|
||||||
|
// Centered content (vertically and horizontally).
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// .l-center>.l-center-i>span
|
||||||
|
.l-center
|
||||||
|
display: table
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
&-i
|
||||||
|
display: table-cell
|
||||||
|
text-align: center
|
||||||
|
vertical-align: middle
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Spacing
|
||||||
|
//
|
||||||
|
|
||||||
|
// Space after block.
|
||||||
|
//
|
||||||
|
// rows - Number of “rows” (one row = default spacer).
|
||||||
|
space(rows=1)
|
||||||
|
margin-bottom: rows*spacer
|
||||||
|
|
||||||
|
// Standard bottom margin.
|
||||||
|
.l-space
|
||||||
|
space()
|
||||||
|
|
||||||
|
// Double bottom margin.
|
||||||
|
.l-double-space
|
||||||
|
space(2)
|
||||||
|
|
||||||
|
// Triple bottom margin.
|
||||||
|
.l-triple-space
|
||||||
|
space(3)
|
||||||
|
|
||||||
|
// Quadruple bottom margin.
|
||||||
|
.l-quad-space
|
||||||
|
space(4)
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Debug stuff
|
||||||
|
///
|
||||||
|
|
||||||
|
if DEBUG
|
||||||
|
.g-debug-col
|
||||||
|
grid-padding()
|
||||||
|
float: left
|
||||||
|
width: grid-width()
|
||||||
|
|
||||||
|
.g-debug-helper
|
||||||
|
position: absolute
|
||||||
|
left: 0
|
||||||
|
right: 0
|
||||||
|
height: 100%
|
||||||
|
min-height: 3000px
|
||||||
|
z-index: 10000
|
||||||
|
overflow: hidden
|
||||||
|
pointer-events: none
|
||||||
|
*
|
||||||
|
height: 100%
|
||||||
|
[data-component="grid"]
|
||||||
|
grid-wrapper()
|
||||||
|
.g-debug-col:before
|
||||||
|
content: ""
|
||||||
|
display: block
|
||||||
|
height: inherit
|
||||||
|
background: hsla(220,40%,50%,.25)
|
|
@ -0,0 +1,195 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Links
|
||||||
|
|
||||||
|
//
|
||||||
|
// Configuration
|
||||||
|
//
|
||||||
|
|
||||||
|
// Link style (default: underline).
|
||||||
|
//
|
||||||
|
// Values:
|
||||||
|
// - underline - text-decoration:underline.
|
||||||
|
// - border - border-bottom:1px solid.
|
||||||
|
// - gradient - Uses CSS gradients to position line under text (cannot change line color on hover).
|
||||||
|
link_style ?= "underline"
|
||||||
|
|
||||||
|
// Link color (default: #1978c8).
|
||||||
|
link_color ?= #1978c8
|
||||||
|
|
||||||
|
// Visited link color.
|
||||||
|
visited_color ?= link_color
|
||||||
|
|
||||||
|
// Hovered link color.
|
||||||
|
hover_color ?= link_color
|
||||||
|
|
||||||
|
// Link underline color.
|
||||||
|
link_underline_color ?= rgba(link_color,.4)
|
||||||
|
|
||||||
|
// Visited link underline color.
|
||||||
|
visited_underline_color ?= rgba(visited_color,.4)
|
||||||
|
|
||||||
|
// Hovered link underline color.
|
||||||
|
hover_underline_color ?= rgba(hover_color,.4)
|
||||||
|
|
||||||
|
// Link underline position (only when link_style == gradient, default: 80%)
|
||||||
|
link_underline_position ?= 80%
|
||||||
|
link_underline_position = 76.5% if link_style == "underline"
|
||||||
|
|
||||||
|
// Pressable links (shifts down by 1px, default: false).
|
||||||
|
link_pressable ?= false
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mixins
|
||||||
|
//
|
||||||
|
|
||||||
|
// Adds link underline (adds nothing for "underline" and "border" types)
|
||||||
|
link-underline(color)
|
||||||
|
if link_style == "gradient"
|
||||||
|
background-image: linear-gradient(to right, color, color)
|
||||||
|
|
||||||
|
// Adds fake link underline (adds nothing for "underline" type)
|
||||||
|
link-fake-underline(color)
|
||||||
|
if link_style != "border"
|
||||||
|
background-image: linear-gradient(to right, color, color 50%, transparent 50%)
|
||||||
|
|
||||||
|
// :hover, :active and :focus states of the link.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// +link-hovers()
|
||||||
|
// color: #bada55
|
||||||
|
link-hovers() {
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus {
|
||||||
|
{block}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All states of the link.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// +link-all-states()
|
||||||
|
// color: @color
|
||||||
|
link-all-states() {
|
||||||
|
&,
|
||||||
|
&:link,
|
||||||
|
&:visited,
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus {
|
||||||
|
{block}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Classes
|
||||||
|
//
|
||||||
|
|
||||||
|
// Pressable element: pointer cursor + disable text selection.
|
||||||
|
.pressable-inset
|
||||||
|
no-select()
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
// Pressable element: shifts down by 1px on click.
|
||||||
|
.pressable
|
||||||
|
@extend .pressable-inset
|
||||||
|
&:active
|
||||||
|
position: relative if link_pressable
|
||||||
|
top: 1px if link_pressable
|
||||||
|
|
||||||
|
// Non-pressable element: cancels .pressable.
|
||||||
|
.no-pressable
|
||||||
|
&,
|
||||||
|
&:hover,
|
||||||
|
&:active
|
||||||
|
cursor: default
|
||||||
|
&:active
|
||||||
|
position: static if link_pressable
|
||||||
|
|
||||||
|
// Remove underline.
|
||||||
|
.no-underline
|
||||||
|
&,
|
||||||
|
&:link,
|
||||||
|
&:visited,
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus
|
||||||
|
text-decoration: none
|
||||||
|
border-bottom: 0
|
||||||
|
background-image: none
|
||||||
|
|
||||||
|
// Link.
|
||||||
|
//
|
||||||
|
// .link_fake - Pseudo link with dashed underline.
|
||||||
|
// .link_quoted - Link in quotes (quotes should be colored but not underlined). Example: a.link.link_quoted>u.
|
||||||
|
.link
|
||||||
|
&,
|
||||||
|
& u
|
||||||
|
@extend .pressable
|
||||||
|
transition: border .1s ease-in-out, color .2s ease-in-out, background .2s ease-in-out
|
||||||
|
cursor: pointer
|
||||||
|
if link_style == "underline"
|
||||||
|
text-decoration: underline
|
||||||
|
else
|
||||||
|
text-decoration: none
|
||||||
|
if link_style == "border"
|
||||||
|
border-bottom-width: 1px
|
||||||
|
border-bottom-style: solid
|
||||||
|
if link_style == "gradient"
|
||||||
|
background-position: 0 link_underline_position
|
||||||
|
background-size: 5px 1px
|
||||||
|
background-repeat: repeat-x
|
||||||
|
|
||||||
|
&,
|
||||||
|
&:link,
|
||||||
|
& u,
|
||||||
|
&:link u
|
||||||
|
link-underline(link_underline_color)
|
||||||
|
color: link_color
|
||||||
|
|
||||||
|
&:visited,
|
||||||
|
&:visited u
|
||||||
|
link-underline(visited_underline_color)
|
||||||
|
color: visited_color
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus,
|
||||||
|
&:hover u,
|
||||||
|
&:active u,
|
||||||
|
&:focus u
|
||||||
|
link-underline(hover_underline_color)
|
||||||
|
color: hover_color
|
||||||
|
|
||||||
|
&_fake
|
||||||
|
if link_style == "border"
|
||||||
|
border-bottom-style: dotted
|
||||||
|
if link_style != "gradient"
|
||||||
|
text-decoration: none
|
||||||
|
background-position: 0 link_underline_position
|
||||||
|
background-size: 5px 1px
|
||||||
|
background-repeat: repeat-x
|
||||||
|
|
||||||
|
&,
|
||||||
|
&:link,
|
||||||
|
&:visited
|
||||||
|
link-fake-underline(link_underline_color)
|
||||||
|
color: link_color
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus
|
||||||
|
link-fake-underline(link_underline_color)
|
||||||
|
color: hover_color
|
||||||
|
|
||||||
|
&_quoted
|
||||||
|
@extend .no-underline
|
||||||
|
|
||||||
|
.no-cssgradients
|
||||||
|
.link
|
||||||
|
text-decoration: underline
|
||||||
|
.link_fake
|
||||||
|
text-decoration: none
|
||||||
|
border-bottom: 1px dotted
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Media queries
|
||||||
|
|
||||||
|
/// Based on https://github.com/jenius/rupture
|
||||||
|
|
||||||
|
// Media query shortcut: viewport width is greater than or equal to specified value.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// .pony
|
||||||
|
// color: #c0ffee
|
||||||
|
// +above(320px)
|
||||||
|
// color: #bada55
|
||||||
|
//
|
||||||
|
// min - Min width.
|
||||||
|
above(min)
|
||||||
|
condition = 'only screen and (min-width: %s)' % min
|
||||||
|
@media condition
|
||||||
|
{block}
|
||||||
|
|
||||||
|
// Media query shortcut: viewport width is less than or equal to specified value.
|
||||||
|
//
|
||||||
|
// max - Max width.
|
||||||
|
below(max)
|
||||||
|
condition = 'only screen and (max-width: %s)' % max
|
||||||
|
@media condition
|
||||||
|
{block}
|
||||||
|
|
||||||
|
// Media query shortcut: viewport width is in between specified values.
|
||||||
|
//
|
||||||
|
// min - Min width.
|
||||||
|
// max - Max width.
|
||||||
|
between(min, max)
|
||||||
|
condition = 'only screen and (min-width: %s) and (max-width: %s)' % (min max)
|
||||||
|
@media condition
|
||||||
|
{block}
|
||||||
|
|
||||||
|
// Media query shortcut: retina screen.
|
||||||
|
retina()
|
||||||
|
@media (min-resolution: 1.5dppx), (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (min-resolution: 144dpi)
|
||||||
|
{block}
|
|
@ -0,0 +1,174 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// Misc functions and mixins
|
||||||
|
|
||||||
|
/// Colors for debug() function.
|
||||||
|
_debug_colors = cyan magenta orange green blue red
|
||||||
|
|
||||||
|
//
|
||||||
|
// Easings
|
||||||
|
//
|
||||||
|
|
||||||
|
/// More here: https://github.com/thoughtbot/bourbon/blob/master/app/assets/stylesheets/addons/_timing-functions.scss
|
||||||
|
|
||||||
|
// Ease in sine.
|
||||||
|
ease-in-sine = cubic-bezier(0.47, 0, 0.745, 0.715)
|
||||||
|
|
||||||
|
// Ease out quint.
|
||||||
|
ease-out-quint = cubic-bezier(0.23,1,0.32,1)
|
||||||
|
|
||||||
|
// Ease out back.
|
||||||
|
ease-out-back = cubic-bezier(0.175,0.885,0.32,1.275)
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Typography and text
|
||||||
|
//
|
||||||
|
|
||||||
|
// Ellipsis text overflow.
|
||||||
|
ellipsis()
|
||||||
|
overflow: hidden
|
||||||
|
text-overflow: ellipsis
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
|
// Tweak inverted text (light on dark) for OS X.
|
||||||
|
tweak-inverted-text()
|
||||||
|
-webkit-font-smoothing: antialiased
|
||||||
|
-moz-osx-font-smoothing: grayscale
|
||||||
|
|
||||||
|
// Enables ligatures in text.
|
||||||
|
enable-ligatures()
|
||||||
|
text-rendering: optimizeLegibility
|
||||||
|
-webkit-font-feature-settings: "liga", "dlig"
|
||||||
|
-moz-font-feature-settings: "liga=1, dlig=1"
|
||||||
|
font-feature-settings: "liga", "dlig"
|
||||||
|
|
||||||
|
// Text selection style.
|
||||||
|
//
|
||||||
|
// color - Text color.
|
||||||
|
// background - Background color.
|
||||||
|
text-selection(color, background)
|
||||||
|
::-moz-selection
|
||||||
|
color: color
|
||||||
|
background: background
|
||||||
|
text-shadow: none
|
||||||
|
::selection
|
||||||
|
color: color
|
||||||
|
background: background
|
||||||
|
text-shadow: none
|
||||||
|
|
||||||
|
// Input placeholder color.
|
||||||
|
//
|
||||||
|
// color - Placeholder color.
|
||||||
|
placeholder-color(color)
|
||||||
|
&::-webkit-input-placeholder
|
||||||
|
color: color
|
||||||
|
&::-moz-placeholder
|
||||||
|
color: color
|
||||||
|
&:-ms-input-placeholder
|
||||||
|
color: color
|
||||||
|
|
||||||
|
// Disables text selection.
|
||||||
|
no-select()
|
||||||
|
-webkit-touch-callout: none
|
||||||
|
user-select: none
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Misc.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Clearfix.
|
||||||
|
clearfix()
|
||||||
|
&:before
|
||||||
|
&:after
|
||||||
|
content: ""
|
||||||
|
display: table
|
||||||
|
&:after
|
||||||
|
clear: both
|
||||||
|
|
||||||
|
// Set element width and height.
|
||||||
|
//
|
||||||
|
// width - Width.
|
||||||
|
// [height] - Height (the same as width if not passed).
|
||||||
|
size(width, height=null)
|
||||||
|
width: width
|
||||||
|
if height
|
||||||
|
height: height
|
||||||
|
else
|
||||||
|
height: width
|
||||||
|
|
||||||
|
// Disables columns.
|
||||||
|
no-cols()
|
||||||
|
position: static
|
||||||
|
display: block
|
||||||
|
float: none
|
||||||
|
width: auto
|
||||||
|
margin-left: 0
|
||||||
|
margin-right: 0
|
||||||
|
|
||||||
|
// Disables transitions.
|
||||||
|
//
|
||||||
|
// imp - Important? (default: false).
|
||||||
|
no-transition(imp=false)
|
||||||
|
/// It is the shortest crossbrowser way
|
||||||
|
if imp
|
||||||
|
transition 0s !important
|
||||||
|
else
|
||||||
|
transition 0s
|
||||||
|
|
||||||
|
// Draws triangle.
|
||||||
|
//
|
||||||
|
// direction - Triangle direction (up, down, left, right).
|
||||||
|
// size - Size (default: 10px).
|
||||||
|
// color - Color (default: black).
|
||||||
|
triangle(direction=up, size=10px, color=#000)
|
||||||
|
/// Borrowed from https://github.com/jenius/roots-css/blob/master/roots-css/utilities.styl.
|
||||||
|
width: 0
|
||||||
|
height: 0
|
||||||
|
if direction is up
|
||||||
|
border-left: size solid transparent
|
||||||
|
border-right: size solid transparent
|
||||||
|
border-bottom: size solid color
|
||||||
|
else if direction is down
|
||||||
|
border-left: size solid transparent
|
||||||
|
border-right: size solid transparent
|
||||||
|
border-top: size solid color
|
||||||
|
else if direction is left
|
||||||
|
border-top: size solid transparent
|
||||||
|
border-bottom: size solid transparent
|
||||||
|
border-right: size solid color
|
||||||
|
else if direction is right
|
||||||
|
border-top: size solid transparent
|
||||||
|
border-bottom: size solid transparent
|
||||||
|
border-left: size solid color
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Draws color outline around an element.
|
||||||
|
//
|
||||||
|
// Works only when DEBUG == true.
|
||||||
|
debug()
|
||||||
|
outline: 1px solid pop(_debug_colors) if DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Internal stuff
|
||||||
|
///
|
||||||
|
|
||||||
|
/// Sticky footer wrapper.
|
||||||
|
///
|
||||||
|
/// h - Footer height.
|
||||||
|
sticky-footer-wrapper(h)
|
||||||
|
position: relative
|
||||||
|
min-height: 100%
|
||||||
|
margin-bottom: h
|
||||||
|
|
||||||
|
/// Sticky footer.
|
||||||
|
///
|
||||||
|
/// h - Footer height.
|
||||||
|
sticky-footer(h)
|
||||||
|
position: absolute
|
||||||
|
left: 0
|
||||||
|
right: 0
|
||||||
|
bottom: 0
|
||||||
|
height: h
|
|
@ -0,0 +1,363 @@
|
||||||
|
// Tâmia © 2013 Artem Sapegin http://sapegin.me
|
||||||
|
// https://github.com/sapegin/tamia
|
||||||
|
// JS core
|
||||||
|
// jQuery and Modernizr aren’t required but very useful
|
||||||
|
|
||||||
|
/*jshint newcap:false*/
|
||||||
|
/*global DEBUG:true, Modernizr:false, console:false*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug mode.
|
||||||
|
*
|
||||||
|
* You can use DEBUG global variable in your scripts to hide some code from minified production version of JavaScript.
|
||||||
|
*
|
||||||
|
* To make it work add to your Gruntfile:
|
||||||
|
*
|
||||||
|
* uglify: {
|
||||||
|
* options: {
|
||||||
|
* compress: {
|
||||||
|
* global_defs: {
|
||||||
|
* DEBUG: !!grunt.option('debug')
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Then if you run `grunt --debug` DEBUG variable will be true and false if you run just `grunt`.
|
||||||
|
*/
|
||||||
|
if (typeof window.DEBUG === 'undefined') window.DEBUG = true;
|
||||||
|
|
||||||
|
;(function(window, jQuery, Modernizr, undefined) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// IE8+
|
||||||
|
if (!document.querySelectorAll) return;
|
||||||
|
|
||||||
|
// Namespace
|
||||||
|
var tamia = window.tamia = {};
|
||||||
|
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
// Debug logger
|
||||||
|
var addBadge = function(args, name) {
|
||||||
|
// Color console badge
|
||||||
|
// Based on https://github.com/jbail/lumberjack
|
||||||
|
var ua = navigator.userAgent.toLowerCase();
|
||||||
|
if (ua.indexOf('chrome') !== -1 || ua.indexOf('firefox') !== -1) {
|
||||||
|
var format = '%c %s %c ' + args.shift();
|
||||||
|
args.unshift(format, 'background:#aa759f; color:#fff', name, 'background:inherit; color:inherit');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args[0] = name + ': ' + args[0];
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
};
|
||||||
|
var logger = function() {
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
var func = args.shift();
|
||||||
|
console[func].apply(console, addBadge(args, 'Tâmia'));
|
||||||
|
};
|
||||||
|
var log = tamia.log = logger.bind(null, 'log');
|
||||||
|
var warn = tamia.warn = logger.bind(null, 'warn');
|
||||||
|
|
||||||
|
// Check optional dependencies
|
||||||
|
if (!jQuery) warn('jQuery not found.');
|
||||||
|
if (!jQuery.Transitions) warn('jQuery Transition Events plugin (tamia/vendor/transition-events.js) not found.');
|
||||||
|
if (!Modernizr) warn('Modernizr not found.');
|
||||||
|
|
||||||
|
// Check required Modernizr features
|
||||||
|
$.each([
|
||||||
|
'csstransitions',
|
||||||
|
'cssgradients',
|
||||||
|
'flexbox',
|
||||||
|
'touch',
|
||||||
|
], function(idx, feature) {
|
||||||
|
if (!(feature in Modernizr)) warn('Modernizr should be built with "' + feature + '" feautre.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var _containersCache;
|
||||||
|
var _components = {};
|
||||||
|
var _initializedAttribute = '_tamia-yep';
|
||||||
|
|
||||||
|
function _getContainers(parent) {
|
||||||
|
return (parent || document).querySelectorAll('[data-component]');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize components.
|
||||||
|
*
|
||||||
|
* @param {Object} components Initializers for each component.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* <div data-component="pony"></div>
|
||||||
|
*
|
||||||
|
* tamia.initComponents({
|
||||||
|
* // New style component
|
||||||
|
* pony: Pony, // class Pony extends Component {...}
|
||||||
|
* // Plain initializer
|
||||||
|
* pony: function(elem) {
|
||||||
|
* // $(elem) === <div data-component="pony">
|
||||||
|
* },
|
||||||
|
* // Initialize jQuery plugins (plain initializer)
|
||||||
|
* jquerypony: function(elem) {
|
||||||
|
* $(elem).pluginmethod({option1: 'val1', options2: 'val2'});
|
||||||
|
* $(elem).pluginmethod2();
|
||||||
|
* },
|
||||||
|
* // Initialize jQuery plugins (shortcut)
|
||||||
|
* jquerypony: {
|
||||||
|
* pluginmethod: {option1: 'val1', options2: 'val2'},
|
||||||
|
* pluginmethod2: ['attr1', 'attr2', 'attr3'],
|
||||||
|
* pluginmethod3: null
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Caveats:
|
||||||
|
*
|
||||||
|
* 1. To initialize components inside container that was hidden or inside dynamically created container use
|
||||||
|
* init.tamia event: `$('.js-container').trigger('init.tamia');`
|
||||||
|
* 2. No components will be initialized twice. It’s safe to trigger init.tamia event multiple times: only new nodes
|
||||||
|
* or nodes that was hidden before will be affected.
|
||||||
|
*/
|
||||||
|
tamia.initComponents = function(components, parent) {
|
||||||
|
var containers;
|
||||||
|
if (parent === undefined) {
|
||||||
|
containers = _containersCache || (_containersCache = _getContainers());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Init all components inside DOM node
|
||||||
|
containers = _getContainers(parent);
|
||||||
|
components = _components;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init components
|
||||||
|
for (var containerIdx = 0, containerCnt = containers.length; containerIdx < containerCnt; containerIdx++) {
|
||||||
|
var container = containers[containerIdx];
|
||||||
|
var componentName = container.getAttribute('data-component');
|
||||||
|
var component = components[componentName];
|
||||||
|
if (!component || container.hasAttribute(_initializedAttribute)) continue;
|
||||||
|
|
||||||
|
var initialized = true;
|
||||||
|
if ('__tamia_cmpnt__' in component) {
|
||||||
|
// New style component
|
||||||
|
initialized = (new component(container)).initializable;
|
||||||
|
}
|
||||||
|
else if (typeof component === 'function') {
|
||||||
|
// Old style component
|
||||||
|
initialized = component(container);
|
||||||
|
}
|
||||||
|
else if (jQuery) {
|
||||||
|
// jQuery plugins shortcut
|
||||||
|
for (var method in component) {
|
||||||
|
var params = component[method];
|
||||||
|
var elem = jQuery(container);
|
||||||
|
if (DEBUG && !jQuery.isFunction(elem[method])) warn('jQuery method "%s" not found (used in "%s" component).', method, componentName);
|
||||||
|
if (jQuery.isArray(params)) {
|
||||||
|
elem[method].apply(elem, params);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elem[method](params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialized !== false) {
|
||||||
|
container.setAttribute(_initializedAttribute, 'yes');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new components to all components array
|
||||||
|
for (var name in components) {
|
||||||
|
_components[name] = components[name];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (jQuery) {
|
||||||
|
|
||||||
|
var _doc = jQuery(document);
|
||||||
|
var _hiddenClass = 'is-hidden';
|
||||||
|
var _transitionClass = 'is-transit';
|
||||||
|
var _appearedEvent = 'appeared.tamia';
|
||||||
|
var _disappearedEvent = 'disappeared.tamia';
|
||||||
|
var _fallbackTimeout = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers Tâmia events (eventname.tamia) on document.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* // Registers enable.tamia event.
|
||||||
|
* tamia.registerEvents({
|
||||||
|
* enable: function(elem) {
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* @param {Object} handlers Handlers list.
|
||||||
|
*/
|
||||||
|
tamia.registerEvents = function(handlers) {
|
||||||
|
var events = $.map(handlers, _tamiaze).join(' ');
|
||||||
|
_doc.on(events, function(event) {
|
||||||
|
if (DEBUG) log('Event "%s":', event.type, event.target);
|
||||||
|
handlers[event.type](event.target);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var _tamiaze = function (handler, name) {
|
||||||
|
return name + '.tamia';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Events
|
||||||
|
*/
|
||||||
|
var _handlers = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init components inside any jQuery node.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* $(document).trigger('init.tamia');
|
||||||
|
* $('.js-container').trigger('init.tamia');
|
||||||
|
*/
|
||||||
|
_handlers.init = function(elem) {
|
||||||
|
tamia.initComponents(undefined, elem);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show element with CSS transition.
|
||||||
|
*
|
||||||
|
* appeared.tamia event will be fired the moment transition ends.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* .dialog
|
||||||
|
* transition: opacity .5s ease-in-out
|
||||||
|
* ...
|
||||||
|
* &.is-hidden
|
||||||
|
* opacity: 0
|
||||||
|
*
|
||||||
|
* <div class="dialog is-hidden js-dialog">...</div>
|
||||||
|
*
|
||||||
|
* $('.js-dialog').trigger('appear.tamia');
|
||||||
|
*/
|
||||||
|
_handlers.appear = function(elem) {
|
||||||
|
elem = $(elem);
|
||||||
|
if (Modernizr && Modernizr.csstransitions) {
|
||||||
|
if (elem.hasClass(_transitionClass) && !elem.hasClass(_hiddenClass)) return;
|
||||||
|
elem.addClass(_transitionClass);
|
||||||
|
setTimeout(function() {
|
||||||
|
elem.removeClass(_hiddenClass);
|
||||||
|
elem.afterTransition(function() {
|
||||||
|
elem.removeClass(_transitionClass);
|
||||||
|
elem.trigger(_appearedEvent);
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elem.removeClass(_hiddenClass);
|
||||||
|
elem.trigger(_appearedEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide element with CSS transition.
|
||||||
|
*
|
||||||
|
* disappeared.tamia event will be fired the moment transition ends.
|
||||||
|
*
|
||||||
|
* Opposite of `appear.tamia` event.
|
||||||
|
*/
|
||||||
|
_handlers.disappear = function(elem) {
|
||||||
|
elem = $(elem);
|
||||||
|
if (Modernizr && Modernizr.csstransitions) {
|
||||||
|
if (elem.hasClass(_transitionClass) && elem.hasClass(_hiddenClass)) return;
|
||||||
|
elem.addClass(_transitionClass);
|
||||||
|
elem.addClass(_hiddenClass);
|
||||||
|
elem.afterTransition(function() {
|
||||||
|
elem.removeClass(_transitionClass);
|
||||||
|
elem.trigger(_disappearedEvent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elem.addClass(_hiddenClass);
|
||||||
|
elem.trigger(_disappearedEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles element’s visibility with CSS transition.
|
||||||
|
*
|
||||||
|
* See `appear.tamia` event for details.
|
||||||
|
*/
|
||||||
|
_handlers.toggle = function(elem) {
|
||||||
|
elem = $(elem);
|
||||||
|
if (elem.hasClass(_hiddenClass)) {
|
||||||
|
_handlers.appear(elem);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_handlers.disappear(elem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tamia.registerEvents(_handlers);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls.
|
||||||
|
*
|
||||||
|
* Fires jQuery event to specified element on click at this element.
|
||||||
|
*
|
||||||
|
* @param data-fire Event name.
|
||||||
|
* @param [data-target] Target element selector.
|
||||||
|
* @param [data-closest] Target element selector: search only through element ancestors.
|
||||||
|
* @param [data-attrs] Comma separated attributes list.
|
||||||
|
*
|
||||||
|
* Either of data-target or data-closest is required.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* <span data-fire="slider-next" data-target=".portfolio" data-attrs="1,2,3">Next</span>
|
||||||
|
* <!-- $('.portfolio').trigger('slider-next', [1, 2, 3]); -->
|
||||||
|
*/
|
||||||
|
_doc.on('click', '[data-fire]', function(event) {
|
||||||
|
var elem = jQuery(event.currentTarget);
|
||||||
|
|
||||||
|
var data = elem.data();
|
||||||
|
if (DEBUG) if (!data.target && !data.closest) return log('You should define either data-target or data-closest on', elem[0]);
|
||||||
|
|
||||||
|
var target = data.target && jQuery(data.target) || elem.closest(data.closest);
|
||||||
|
if (DEBUG) if (!target.length) return log('Target element %s not found for', data.target || data.closest, elem[0]);
|
||||||
|
|
||||||
|
var attrs = data.attrs;
|
||||||
|
if (DEBUG) log('Fire "%s" with attrs [%s] on', data.fire, attrs || '', target);
|
||||||
|
target.trigger(data.fire, attrs ? attrs.split(/[;, ]/) : undefined);
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grid helper.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* <div data-component="grid"></div>
|
||||||
|
*/
|
||||||
|
if (DEBUG) tamia.initComponents({
|
||||||
|
grid: function(elem) {
|
||||||
|
elem = $(elem);
|
||||||
|
elem
|
||||||
|
.addClass('g-row')
|
||||||
|
.html(
|
||||||
|
new Array((elem.data('columns') || 12) + 1).join('<b class="g-debug-col" style="height:'+document.documentElement.scrollHeight+'px"></b>')
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}(window, window.jQuery, window.Modernizr));
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Andrey “A.I.” Sitnik <andrey@sitnik.ru>,
|
||||||
|
* sponsored by Evil Martians.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
;(function($) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Common methods and properties for jQuery Transition Events plugin.
|
||||||
|
// Mostly for internal usage, but maybe helpful for some hack stuff:
|
||||||
|
//
|
||||||
|
// if ( $.Transitions.isSupported() ) {
|
||||||
|
// // CSS Transitions is supported
|
||||||
|
// }
|
||||||
|
$.Transitions = {
|
||||||
|
|
||||||
|
// Hash of property name to event name with vendor prefixes.
|
||||||
|
// It is used to detect prefix.
|
||||||
|
_names: {
|
||||||
|
// Webkit must be on bottom, because Opera try to use webkit
|
||||||
|
// prefix.
|
||||||
|
'transition': 'transitionend',
|
||||||
|
'OTransition': 'oTransitionEnd',
|
||||||
|
'WebkitTransition': 'webkitTransitionEnd',
|
||||||
|
'MozTransition': 'transitionend'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Return array of milliseconds for CSS value of `transition-duration`.
|
||||||
|
// It’s used in `$.fn.afterTransition`.
|
||||||
|
_parseTimes: function (string) {
|
||||||
|
var value, array = string.split(/,\s*/);
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
value = array[i];
|
||||||
|
array[i] = parseFloat(value);
|
||||||
|
if ( value.match(/\ds/) ) {
|
||||||
|
array[i] = array[i] * 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Autodetect vendor prefix and return `transitionend` event name.
|
||||||
|
//
|
||||||
|
// If browser didn’t support CSS Transitions it will return `false`.
|
||||||
|
getEvent: function () {
|
||||||
|
var finded = false;
|
||||||
|
for ( var prop in this._names ) {
|
||||||
|
if ( typeof(document.body.style[prop]) != 'undefined' ) {
|
||||||
|
finded = this._names[prop];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getEvent = function () {
|
||||||
|
return finded;
|
||||||
|
};
|
||||||
|
|
||||||
|
return finded;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Alias to vendor prefixed `requestAnimationFrame`. Will be replace
|
||||||
|
// by native function after first call.
|
||||||
|
animFrame: function (callback) {
|
||||||
|
var raf = window.requestAnimationFrame ||
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.msRequestAnimationFrame;
|
||||||
|
if ( raf ) {
|
||||||
|
this.animFrame = function (callback) {
|
||||||
|
return raf.call(window, callback);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.animFrame = function (callback) {
|
||||||
|
return setTimeout(callback, 10);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.animFrame(callback);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Return `true` if browser support CSS Transitions.
|
||||||
|
isSupported: function () {
|
||||||
|
return this.getEvent() !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// jQuery node methods.
|
||||||
|
$.extend($.fn, {
|
||||||
|
|
||||||
|
// Call `callback` after CSS Transition finish
|
||||||
|
// `delay + (durationPart * duration)`. It will call `callback` only
|
||||||
|
// once, in difference from `transitionEnd`.
|
||||||
|
//
|
||||||
|
// $('.show-video').click(function () {
|
||||||
|
// $('.slider').addClass('video-position').afterTransition(
|
||||||
|
// function () { autoPlayVideo(); });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// You can set `durationPart` to call `callback` in the middle of
|
||||||
|
// transition:
|
||||||
|
//
|
||||||
|
// $('.fliper').addClass('rotate').afterTransition(0.5, function () {
|
||||||
|
// $(this).find('.backface').show();
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// Callback will get object with `propertyName` and `elapsedTime`
|
||||||
|
// properties. If transition is set to difference properties, it will
|
||||||
|
// be called on every property.
|
||||||
|
//
|
||||||
|
// This method doesn’t check, that transition is really finished (it can
|
||||||
|
// be canceled in the middle).
|
||||||
|
afterTransition: function (durationPart, callback) {
|
||||||
|
if ( typeof(callback) == 'undefined' ) {
|
||||||
|
callback = durationPart;
|
||||||
|
durationPart = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !$.Transitions.isSupported() ) {
|
||||||
|
for (var i = 0; i < this.length; i++) {
|
||||||
|
callback.call(this[i], {
|
||||||
|
type: 'aftertransition',
|
||||||
|
elapsedTime: 0,
|
||||||
|
propertyName: '',
|
||||||
|
currentTarget: this[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < this.length; i++) {
|
||||||
|
var el = $(this[i]);
|
||||||
|
var props = el.css('transition-property').split(/,\s*/);
|
||||||
|
var durations = el.css('transition-duration');
|
||||||
|
var delays = el.css('transition-delay');
|
||||||
|
|
||||||
|
durations = $.Transitions._parseTimes(durations);
|
||||||
|
delays = $.Transitions._parseTimes(delays);
|
||||||
|
|
||||||
|
var prop, duration, delay, after, elapsed;
|
||||||
|
for (var j = 0; j < props.length; j++) {
|
||||||
|
prop = props[j];
|
||||||
|
duration = durations[ durations.length == 1 ? 0 : j ];
|
||||||
|
delay = delays[ delays.length == 1 ? 0 : j ];
|
||||||
|
after = delay + (duration * durationPart);
|
||||||
|
elapsed = duration * durationPart / 1000;
|
||||||
|
|
||||||
|
(function (el, prop, after, elapsed) {
|
||||||
|
setTimeout(function () {
|
||||||
|
$.Transitions.animFrame(function () {
|
||||||
|
callback.call(el[0], {
|
||||||
|
type: 'aftertransition',
|
||||||
|
elapsedTime: elapsed,
|
||||||
|
propertyName: prop,
|
||||||
|
currentTarget: el[0]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, after);
|
||||||
|
})(el, prop, after, elapsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Set `callback` to listen every CSS Transition finish.
|
||||||
|
// It will call `callback` on every finished transition,
|
||||||
|
// in difference from `afterTransition`.
|
||||||
|
//
|
||||||
|
// It just bind to `transitionend` event, but detect vendor prefix.
|
||||||
|
//
|
||||||
|
// Callback will get event object with `propertyName` and `elapsedTime`
|
||||||
|
// properties. If transition is set to difference properties, it will
|
||||||
|
// be called on every property.
|
||||||
|
//
|
||||||
|
// Note, that `callback` will get original event object, not from
|
||||||
|
// jQuery.
|
||||||
|
//
|
||||||
|
// var slider = $('.slider').transitionEnd(function () {
|
||||||
|
// if ( slider.hasClass('video-position') ) {
|
||||||
|
// autoPlayVideo();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// $('.show-video').click(function () {
|
||||||
|
// slider.addClass('video-position');
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// If transition will be canceled before finish, event won’t be fired.
|
||||||
|
transitionEnd: function (callback) {
|
||||||
|
for (var i = 0; i < this.length; i++) {
|
||||||
|
this[i].addEventListener($.Transitions.getEvent(), function (e) {
|
||||||
|
callback.call(this, e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this, jQuery);
|
|
@ -0,0 +1,17 @@
|
||||||
|
<div class="social-likes{{? $.type === 'vertical' }} social-likes_vertical{{?}}{{? $.type === 'single' }} social-likes_single{{?}}{{? $.light }} social-likes_light{{?}}"{{? !$.counters }} data-counters="no"{{?}}{{? $.url }} data-url="{{=$.url}}"{{?}}{{? $.title }} data-title="{{=$.title}}"{{?}}{{? $.type === 'single' }} data-single-title="{{=$.singleTitle}}"{{?}}>
|
||||||
|
|
||||||
|
{{? $.site_facebook }}<div class="facebook" title="{{=$.titleFacebook}}">Facebook</div>{{?}}
|
||||||
|
|
||||||
|
{{? $.site_twitter }}<div class="twitter" {{? $.twitter_via }} data-via="{{=$.twitter_via}}"{{?}} {{? $.twitter_related }} data-related="{{=$.twitter_related}}"{{?}} title="{{=$.titleTwitter}}">Twitter</div>{{?}}
|
||||||
|
|
||||||
|
{{? $.site_mailru }}<div class="mailru" title="Поделиться ссылкой в Моём мире">Мой мир</div>{{?}}
|
||||||
|
|
||||||
|
{{? $.site_vkontakte }}<div class="vkontakte" title="Поделиться ссылкой во Вконтакте">Вконтакте</div>{{?}}
|
||||||
|
|
||||||
|
{{? $.site_odnoklassniki }}<div class="odnoklassniki" title="Поделиться ссылкой в Одноклассниках">Одноклассники</div>{{?}}
|
||||||
|
|
||||||
|
{{? $.site_plusone }}<div class="plusone" title="{{=$.titlePlusone}}">Google+</div>{{?}}
|
||||||
|
|
||||||
|
{{? $.site_pinterest }}<div class="pinterest" title="{{=$.titlePinterest}}" data-media="{{=$.pinterest_media}}">Pinterest</div>{{?}}
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,21 @@
|
||||||
|
$.tagsClasses = function(prefix, tags) {
|
||||||
|
var classes = [prefix];
|
||||||
|
for (var tagIdx = 0; tagIdx < tags.length; tagIdx++) {
|
||||||
|
classes.push(prefix + '_' + tags[tagIdx]);
|
||||||
|
}
|
||||||
|
return classes.join(' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
$.getPage = function(page) {
|
||||||
|
return $.map[$.lang + '/' + page];
|
||||||
|
};
|
||||||
|
|
||||||
|
$.getBodyClasses = function() {
|
||||||
|
if (!$.bodyClasses) return '';
|
||||||
|
return $.bodyClasses.join(' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
$.getTranslationUrl = function(lang) {
|
||||||
|
var translation = $.map[$.path.replace($.lang, lang)];
|
||||||
|
return translation ? translation.url : $.map[lang + '/index'].url;
|
||||||
|
};
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{=$.lang}}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Social Likes</title>
|
||||||
|
<meta name="generator" content="Social Likes: http://sapegin.github.com/social-likes/">
|
||||||
|
<link rel="stylesheet" href="social-likes_{{=$.skin}}.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/{{=$.jquery_ver}}/jquery.min.js"><\/script>
|
||||||
|
<script src="social-likes.min.js"><\/script>
|
||||||
|
|
||||||
|
{{=$.html}}
|
||||||
|
|
||||||
|
<p><small>{{=$.footer}}</small></p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<link rel="stylesheet" href="social-likes_{{=$.skin}}.css">
|
||||||
|
...
|
||||||
|
<script src="jquery.min.js"><\/script>
|
||||||
|
<script src="social-likes.min.js"><\/script>
|
||||||
|
...
|
|
@ -0,0 +1,249 @@
|
||||||
|
<f:template xmlns:f="http://fest.mail.ru" context_name="$">
|
||||||
|
<f:doctype>html</f:doctype>
|
||||||
|
<f:script src="./functions.js"/>
|
||||||
|
<html lang="{$.lang}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>
|
||||||
|
<f:value>$.pageTitle</f:value>
|
||||||
|
</title>
|
||||||
|
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||||
|
<meta name="viewport" content="width=1024px"/>
|
||||||
|
<meta name="format-detection" content="telephone=no"/>
|
||||||
|
<meta name="description" content="{$.descriptionHead||$.description}"/>
|
||||||
|
|
||||||
|
<script src="{$.files.modernizr}"></script>
|
||||||
|
<link rel="stylesheet" href="{$.files.css}"/>
|
||||||
|
<link id="styles_classic" rel="stylesheet" href="{$.files.slcss_classic}"/>
|
||||||
|
<link id="styles_flat" rel="stylesheet" href="{$.files.slcss_flat}" disabled="disabled"/>
|
||||||
|
<link id="styles_birman" rel="stylesheet" href="{$.files.slcss_birman}" disabled="disabled"/>
|
||||||
|
|
||||||
|
<link rel="image_src" href="http://sapegin.github.com/social-likes/img/social-likes.png"/>
|
||||||
|
<meta property="og:image" content="http://sapegin.github.com/social-likes/img/social-likes.png"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="forkme">
|
||||||
|
<a href="https://github.com/sapegin/social-likes" class="forkme-i">Fork me on GitHub</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<div class="language-switcher">
|
||||||
|
<a href="{$.translationLink}">
|
||||||
|
<f:value>$.translationTitle</f:value>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>
|
||||||
|
<f:value>$.name</f:value>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
<p>
|
||||||
|
<f:value output="text">$.description</f:value>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="preview preview_horizontal js-preview"></div>
|
||||||
|
|
||||||
|
<form class="builder form form_full" data-component="builder">
|
||||||
|
<input type="hidden" name="lang" value="{$.lang}"/>
|
||||||
|
<input type="hidden" name="titleFacebook" value="{$.titleFacebook}"/>
|
||||||
|
<input type="hidden" name="titleTwitter" value="{$.titleTwitter}"/>
|
||||||
|
<input type="hidden" name="titlePlusone" value="{$.titlePlusone}"/>
|
||||||
|
<input type="hidden" name="titleLivejournal" value="{$.titleLivejournal}"/>
|
||||||
|
<input type="hidden" name="titlePinterest" value="{$.titlePinterest}"/>
|
||||||
|
<input type="hidden" name="singleTitle" value="{$.singleTitle}"/>
|
||||||
|
|
||||||
|
<!-- Skin -->
|
||||||
|
<div class="builder__row">
|
||||||
|
<div class="builder__label">
|
||||||
|
<f:value>$.builderSkin</f:value>
|
||||||
|
</div>
|
||||||
|
<div class="builder__widget">
|
||||||
|
<div class="switcher">
|
||||||
|
<input class="switcher__input" id="skin_classic" type="radio" name="skin" value="classic" checked="checked"/>
|
||||||
|
<label class="switcher__label" for="skin_classic"><f:value>$.builderSkinClassic</f:value></label>
|
||||||
|
<input class="switcher__input" id="skin_flat" type="radio" name="skin" value="flat"/>
|
||||||
|
<label class="switcher__label" for="skin_flat"><f:value>$.builderSkinFlat</f:value></label>
|
||||||
|
<input class="switcher__input" id="skin_birman" type="radio" name="skin" value="birman"/>
|
||||||
|
<label class="switcher__label" for="skin_birman"><f:value>$.builderSkinBirman</f:value></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Type (look) -->
|
||||||
|
<div class="builder__row">
|
||||||
|
<div class="builder__label">
|
||||||
|
<f:value>$.builderType</f:value>
|
||||||
|
</div>
|
||||||
|
<div class="builder__widget">
|
||||||
|
<div class="switcher">
|
||||||
|
<input class="switcher__input" id="type_horizontal" type="radio" name="type" value="horizontal" checked="checked"/>
|
||||||
|
<label class="switcher__label" for="type_horizontal"><f:value>$.builderTypeHorizontal</f:value></label>
|
||||||
|
<input class="switcher__input" id="type_vertical" type="radio" name="type" value="vertical"/>
|
||||||
|
<label class="switcher__label" for="type_vertical"><f:value>$.builderTypeVertical</f:value></label>
|
||||||
|
<input class="switcher__input" id="type_single" type="radio" name="type" value="single"/>
|
||||||
|
<label class="switcher__label" for="type_single"><f:value>$.builderTypeSingle</f:value></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="builder__row">
|
||||||
|
<div class="builder__widget">
|
||||||
|
<div class="builder__checkbox checkbox">
|
||||||
|
<input class="checkbox__input" id="counters" type="checkbox" name="counters" value="1" checked="checked"/>
|
||||||
|
<label class="checkbox__label" for="counters">
|
||||||
|
<span class="checkbox__button"></span>
|
||||||
|
<f:space/>
|
||||||
|
<span class="checkbox__text"><f:value>$.builderCounters</f:value></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="builder__checkbox checkbox js-light is-hidden">
|
||||||
|
<input class="checkbox__input" id="light" type="checkbox" name="light" value="1"/>
|
||||||
|
<label class="checkbox__label" for="light">
|
||||||
|
<span class="checkbox__button"></span>
|
||||||
|
<f:space/>
|
||||||
|
<span class="checkbox__text"><f:value>$.builderLight</f:value></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="builder__row">
|
||||||
|
<div class="builder__label">
|
||||||
|
<f:value>$.builderSites</f:value>
|
||||||
|
</div>
|
||||||
|
<div class="builder__widget builder__sites group">
|
||||||
|
<f:for iterate="$.common.sites" index="i" value="site">
|
||||||
|
<f:if test="!site.langs || site.langs.indexOf($.lang) !== -1">
|
||||||
|
<div class="builder__checkbox checkbox">
|
||||||
|
<input class="checkbox__input" id="site_{site.id}" type="checkbox" name="site_{site.id}" value="1">
|
||||||
|
<f:attributes>
|
||||||
|
<f:if test="site.checked">
|
||||||
|
<f:attribute name="checked" value="checked"/>
|
||||||
|
</f:if>
|
||||||
|
</f:attributes>
|
||||||
|
</input>
|
||||||
|
<label class="checkbox__label" for="site_{site.id}">
|
||||||
|
<span class="checkbox__button"></span>
|
||||||
|
<f:space/>
|
||||||
|
<span class="checkbox__text">
|
||||||
|
<f:choose>
|
||||||
|
<f:when test="typeof site.name === 'string'">
|
||||||
|
<f:value>site.name</f:value>
|
||||||
|
</f:when>
|
||||||
|
<f:otherwise>
|
||||||
|
<f:value>site.name[$.lang]</f:value>
|
||||||
|
</f:otherwise>
|
||||||
|
</f:choose>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</f:if>
|
||||||
|
</f:for>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="builder__row">
|
||||||
|
<label for="url" class="builder__label">
|
||||||
|
<f:value>$.builderUrl</f:value>
|
||||||
|
</label>
|
||||||
|
<div class="builder__widget">
|
||||||
|
<input type="text" name="url" value="" placeholder="{$.builderUrlHelp}" class="field"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="builder__row">
|
||||||
|
<label for="title" class="builder__label">
|
||||||
|
<f:value>$.builderTitle</f:value>
|
||||||
|
</label>
|
||||||
|
<div class="builder__widget">
|
||||||
|
<input type="text" name="title" value="" placeholder="{$.builderTitleHelp}" class="field"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="builder__row js-twitter-extra is-hidden">
|
||||||
|
<div class="l-row">
|
||||||
|
<div class="l-half">
|
||||||
|
<label for="twitter_via" class="builder__label">
|
||||||
|
<f:value>$.builderTwitterVia</f:value>
|
||||||
|
</label>
|
||||||
|
<div class="builder__widget">
|
||||||
|
<input type="text" name="twitter_via" value="" placeholder="{$.builderTwitterViaHelp}" class="field"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="l-half">
|
||||||
|
<label for="twitter_related" class="builder__label">
|
||||||
|
<f:value>$.builderTwitterRelated</f:value>
|
||||||
|
</label>
|
||||||
|
<div class="builder__widget">
|
||||||
|
<input type="text" name="twitter_related" value="" placeholder="{$.builderTwitterRelatedHelp}" class="field"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="builder__row js-pinterest-extra is-hidden">
|
||||||
|
<label for="pinterest_media" class="builder__label">
|
||||||
|
<f:value>$.builderPinterestMedia</f:value>
|
||||||
|
</label>
|
||||||
|
<div class="builder__widget">
|
||||||
|
<input type="text" name="pinterest_media" value="" placeholder="{$.builderPinterestMediaHelp}" class="field"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre class="code-i"><code class="language-markup js-code"></code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="download-row">
|
||||||
|
<div class="download-row__links">
|
||||||
|
<div class="download-row__button">
|
||||||
|
<a href="https://github.com/sapegin/social-likes/zipball/master" class="big-button js-download" download="social-likes.zip"><f:value>$.downloadArchive</f:value></a>
|
||||||
|
</div>
|
||||||
|
<f:space/>
|
||||||
|
<nobr>
|
||||||
|
<f:value>$.or</f:value>
|
||||||
|
<f:space/>
|
||||||
|
<a href="https://github.com/sapegin/social-likes"><f:value>$.browseCode</f:value></a>
|
||||||
|
<f:space/>
|
||||||
|
<f:value>$.onGitHub</f:value>
|
||||||
|
</nobr>
|
||||||
|
</div>
|
||||||
|
<div class="download-row__descr"><f:value output="text">$.archiveContains</f:value></div>
|
||||||
|
</div>
|
||||||
|
<form id="download-proxy" action="http://api.sapegin.me/social-likes-proxy/proxy.php" method="post">
|
||||||
|
<input type="hidden" name="content" value=""/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="docs">
|
||||||
|
<f:value output="text">$.docs</f:value>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<f:value output="text">$.footer</f:value>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/plain" id="build_tmpl"><f:insert src="build.tmpl.html"/></script>
|
||||||
|
<script type="text/plain" id="prepend_tmpl"><f:insert src="prepend.tmpl.html"/></script>
|
||||||
|
<script type="text/plain" id="index_tmpl"><f:insert src="index.tmpl.html"/></script>
|
||||||
|
<script type="text/plain" id="index_footer_tmpl"><f:value output="text">$.archiveFooter</f:value></script>
|
||||||
|
|
||||||
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
||||||
|
<script src="{$.files.js}"></script>
|
||||||
|
<f:choose>
|
||||||
|
<f:when test="$.debug">
|
||||||
|
<script src="src/social-likes.js"></script>
|
||||||
|
</f:when>
|
||||||
|
<f:otherwise>
|
||||||
|
<script src="{$.files.sljs}"></script>
|
||||||
|
</f:otherwise>
|
||||||
|
</f:choose>
|
||||||
|
|
||||||
|
<!-- Yandex.Metrika counter --><script>(function (d, w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter6395488 = new Ya.Metrika({id:6395488, clickmap:true, trackLinks:true, webvisor:true}); } catch(e) { } }); var n = d.getElementsByTagName("script")[0], s = d.createElement("script"), f = function () { n.parentNode.insertBefore(s, n); }; s.type = "text/javascript"; s.async = true; s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js"; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f); } else { f(); } })(document, window, "yandex_metrika_callbacks");</script><noscript><div><img src="//mc.yandex.ru/watch/6395488" style="position:absolute; left:-9999px;" alt="" /></div></noscript><!-- /Yandex.Metrika counter -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</f:template>
|
16
package.json
|
@ -28,9 +28,13 @@
|
||||||
"jquery": ">=1.8"
|
"jquery": ">=1.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer-stylus": "0.3.0",
|
"autoprefixer-stylus": "~0.3.0",
|
||||||
|
"csso-stylus": "0.0.3",
|
||||||
|
"gh-pages": "~0.8.0",
|
||||||
"grunt": "~0.4.5",
|
"grunt": "~0.4.5",
|
||||||
"grunt-cli": "~0.1.13",
|
"grunt-cli": "~0.1.13",
|
||||||
|
"grunt-contrib-concat": "~0.5.1",
|
||||||
|
"grunt-contrib-connect": "~0.11.2",
|
||||||
"grunt-contrib-imagemin": "~0.8.1",
|
"grunt-contrib-imagemin": "~0.8.1",
|
||||||
"grunt-contrib-jshint": "~0.10.0",
|
"grunt-contrib-jshint": "~0.10.0",
|
||||||
"grunt-contrib-stylus": "~0.20.0",
|
"grunt-contrib-stylus": "~0.20.0",
|
||||||
|
@ -38,13 +42,19 @@
|
||||||
"grunt-contrib-watch": "~0.6.1",
|
"grunt-contrib-watch": "~0.6.1",
|
||||||
"grunt-csso": "~0.6.3",
|
"grunt-csso": "~0.6.3",
|
||||||
"grunt-jscs-checker": "~0.7.1",
|
"grunt-jscs-checker": "~0.7.1",
|
||||||
|
"grunt-modernizr": "~1.0.1",
|
||||||
|
"grunt-replace": "~0.11.0",
|
||||||
|
"grunt-sweet": "~0.2.2",
|
||||||
"grunt-webfont": "~0.4.8",
|
"grunt-webfont": "~0.4.8",
|
||||||
"load-grunt-tasks": "~0.6.0"
|
"load-grunt-tasks": "~0.6.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "grunt",
|
"build": "grunt",
|
||||||
"test": "grunt",
|
"test": "grunt",
|
||||||
"replace-version": "grunt replace:version",
|
"publish": "npm run update-gh-pages && npm run build-gh-pages && npm run publish-gh-pages",
|
||||||
"build-gh-pages": "scripts/update-gh-pages.sh"
|
"update-gh-pages": "mkdir -p gh-pages/public/src && cp dist/* gh-pages/public/src/ && cp src/social-likes.js gh-pages/public/src/",
|
||||||
|
"build-gh-pages": "cd gh-pages && grunt && cd ..",
|
||||||
|
"publish-gh-pages": "gh-pages -d gh-pages/public",
|
||||||
|
"make-debug-symlinks": "ln -s . gh-pages/public/social-likes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|