├── .gitignore
├── project.json
├── app
├── rulesets
│ ├── rulesets.json
│ └── flexbox.cheats
│ │ ├── fx-img
│ │ ├── display_flex.svg
│ │ ├── align-items_baseline.svg
│ │ ├── flex-wrap_nowrap.svg
│ │ ├── align-items_center.svg
│ │ ├── align-items_stretch.svg
│ │ ├── align-items_flex-end.svg
│ │ ├── justify-content_center.svg
│ │ ├── align-items_flex-start.svg
│ │ ├── justify-content_flex-end.svg
│ │ ├── justify-content_flex-start.svg
│ │ ├── justify-content_space-around.svg
│ │ ├── justify-content_space-between.svg
│ │ ├── flex-direction_column.svg
│ │ ├── flex-direction_column-reverse.svg
│ │ ├── flex-direction_row.svg
│ │ ├── flex-direction_row-reverse.svg
│ │ ├── align-content_center.svg
│ │ ├── align-content_flex-end.svg
│ │ ├── align-content_stretch.svg
│ │ ├── align-content_flex-start.svg
│ │ ├── align-content_space-around.svg
│ │ ├── align-content_space-between.svg
│ │ ├── display_inline-flex.svg
│ │ ├── align-self_auto.svg
│ │ ├── align-self_flex-end.svg
│ │ ├── align-self_flex-start.svg
│ │ ├── align-self_stretch.svg
│ │ ├── flex-grow_1.svg
│ │ ├── align-self_baseline.svg
│ │ ├── align-self_center.svg
│ │ ├── flex-wrap_wrap.svg
│ │ ├── flex-grow_0.svg
│ │ ├── flex-wrap_wrap-reverse.svg
│ │ ├── flex-shrink_1.svg
│ │ ├── flex-shrink_0.svg
│ │ └── order_0.svg
│ │ └── flexbox.json
├── list.php
├── index.txt
├── _index.html
├── index.php
├── app.php
└── assets
│ ├── js
│ ├── jquery.hotkeys.js
│ ├── fragment.js
│ ├── yogert.js
│ └── string.js
│ ├── scss
│ └── yogert.scss
│ └── css
│ └── yogert.css
├── package.json
├── README.md
├── Gruntfile.js
└── LICENCE.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | psd
3 | notes
4 |
--------------------------------------------------------------------------------
/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Vocabs"
3 | }
4 |
--------------------------------------------------------------------------------
/app/rulesets/rulesets.json:
--------------------------------------------------------------------------------
1 | {
2 | "flexbox": {
3 | "title": "Flexbox cheatsheet",
4 | "help-text": "",
5 | "credits": {
6 | "@sakamies": "http://twitter.com/sakamies"
7 | },
8 | "specs": {
9 | "CSS-Tricks: A Complete Guide to Flexbox": "http://css-tricks.com/snippets/css/a-guide-to-flexbox/"
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Cheatsheets",
3 | "version": "3.0.0",
4 | "description": "Cheatsheets",
5 | "devDependencies": {
6 | "grunt": "^1.0.1",
7 | "grunt-autoprefixer": "^3.0.4",
8 | "grunt-contrib-watch": "^1.0.0",
9 | "grunt-sass": "^1.2.0"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/sakamies/vocabs"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/list.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flexbox Cheatsheet
6 |
7 |
8 |
9 |
10 |
11 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CSS Cheats
2 |
3 | CSS Cheatsheets with icons for quick copy & paste.
4 |
5 | ----
6 |
7 | ## Making new cheatsheets
8 |
9 | First off of course, fork the repo. Cheatsheets are JSON files in app/rulesets/cheatsheet_name.cheats. A cheatsheet contains css rules, each with a selector and some declarations. Check out flexbox.cheats/flexbox.json, it's rather simple. After you've made your new something.cheats folder, add some info about your cheatsheet to rulesets.json. Use the flexbox entry as an example.
10 |
11 | For some declarations it makes sense to make a little image to make it easier to remember what the values do. The filename needs to be in the format `{property-name}_{value}.svg`.
12 |
13 | When you're done, send a pull request to get the cheatsheet added to the app.
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | grunt.initConfig({
4 | pkg: grunt.file.readJSON('package.json'),
5 | sass: {
6 | app: {
7 | files: {
8 | 'app/assets/css/yogert.css': 'app/assets/scss/yogert.scss',
9 | }
10 | },
11 | },
12 | autoprefixer: {
13 | app: {
14 | files: {
15 | 'app/assets/css/yogert.css': 'app/assets/css/yogert.css'
16 | }
17 | },
18 | },
19 | watch: {
20 | app: {
21 | files: [
22 | 'app/assets/scss/*.scss',
23 | ],
24 | tasks: ['sass:app', 'autoprefixer:app'],
25 | options: {
26 | livereload: true,
27 | interrupt: true,
28 | }
29 | },
30 | }
31 | });
32 |
33 | grunt.loadNpmTasks('grunt-contrib-watch');
34 | grunt.loadNpmTasks('grunt-sass');
35 | grunt.loadNpmTasks('grunt-autoprefixer');
36 |
37 | grunt.registerTask('serve', ['devserver']);
38 | grunt.registerTask('default', ['watch']);
39 |
40 | };
41 |
--------------------------------------------------------------------------------
/LICENCE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Ville Vanninen (@sakamies)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/index.txt:
--------------------------------------------------------------------------------
1 | Title: Flexbox cheatsheet
2 | ----
3 | Author: Ville V. Vanninen
4 | ----
5 | Blurb: Make your own css cheats, starting with flexbox
6 | ----
7 | Text:
8 | You just love making product grids with html & css, right? Didn't think so. Flexbox is a great tool for making nice layouts for lists of things, but configuring it in code is a dog fart and trying to use photoshop and the like to make a grid of items, well forget it.
9 |
10 | Try this: Make a nice looking (flexible) item. Generate a bunch of them with varying data and click around to choose how they behave in the flexbox. Make a nice flexbox layout. Then get the css and use it in your project.
11 |
12 | When you're done, here's the best guide out there to using flexbox properties on your own: [A Complete Guide to Flexbox](http://css-tricks.com/snippets/css/a-guide-to-flexbox/)
13 |
14 | I'm calling this yogert, but Flexbox cheatsheet is a bit more understandable. Part yoga, part yogurt and doesn't smell.
15 |
16 |
17 |
18 | You should be using autoprefixer, so Yogert only generates the flexbox syntax according to the latest specs. Internally Yogert uses prefixfree for browser compatibility, because it works in the browser. You shouldn't use prefixfree for production sites, please use autoprefixer. (Unless you're making a browser based css generator of course.)
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/display_flex.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | display_flex
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flexbox Cheatsheet
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
24 |
25 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-items_baseline.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-items_baseline
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/flexbox.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "selector": ".container",
5 | "declarations": [
6 | [
7 | {"display": "flex"},
8 | {"display": "inline-flex"}
9 | ],
10 | [
11 | {"flex-direction": "row"},
12 | {"flex-direction": "row-reverse"},
13 | {"flex-direction": "column"},
14 | {"flex-direction": "column-reverse"}
15 | ],
16 | [
17 | {"flex-wrap": "nowrap"},
18 | {"flex-wrap": "wrap"},
19 | {"flex-wrap": "wrap-reverse"}
20 | ],
21 | [
22 | {"justify-content": "flex-start"},
23 | {"justify-content": "center"},
24 | {"justify-content": "flex-end"},
25 | {"justify-content": "space-between"},
26 | {"justify-content": "space-around"}
27 | ],
28 | [
29 | {"align-items":"flex-start"},
30 | {"align-items": "center"},
31 | {"align-items": "flex-end"},
32 | {"align-items": "stretch"},
33 | {"align-items": "baseline"}
34 | ],
35 | [
36 | {"align-content": "flex-start"},
37 | {"align-content": "center"},
38 | {"align-content": "flex-end"},
39 | {"align-content": "space-between"},
40 | {"align-content": "space-around"},
41 | {"align-content": "stretch"}
42 | ]
43 | ]
44 | },
45 | {
46 | "selector": ".item",
47 | "declarations": [
48 | [
49 | {"order": "0"}
50 | ],
51 | [
52 | {"flex-grow": "0"},
53 | {"flex-grow": "1"}
54 | ],
55 | [
56 | {"flex-shrink": "0"},
57 | {"flex-shrink": "1"}
58 | ],
59 | [
60 | {"flex-basis": "auto"}
61 | ],
62 | [
63 | {"align-self": "auto"},
64 | {"align-self": "flex-start"},
65 | {"align-self": "center"},
66 | {"align-self": "flex-end"},
67 | {"align-self": "baseline"},
68 | {"align-self": "stretch"}
69 | ]
70 | ]
71 | }
72 | ]
73 | }
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-wrap_nowrap.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-wrap_nowrap
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/index.php:
--------------------------------------------------------------------------------
1 | $url) {
6 | $links .= ''.$name.' ';
7 | }
8 | return $links;
9 | }
10 |
11 | function specsLinks($links) {
12 | $html = '';
13 | $html .= '';
14 | foreach ($links as $text => $url) {
15 | $html .= '';
16 | $html .= ''.$text.' ';
17 | $html .= ' ';
18 | }
19 | $html .= ' ';
20 | return $html;
21 | }
22 |
23 | // Use ugly urls for local dev
24 | $localhosts = array('localhost', 'cheat.dev');
25 | $uglyUrls = in_array($_SERVER['HTTP_HOST'], $localhosts);
26 | // Find out if ugly, but say if pretty, lifts the mood
27 | if ($uglyUrls == true) {
28 | $path = '/';
29 | } else {
30 | $path = 'http://apps.workflower.fi/css-cheats/';
31 | };
32 |
33 | $sets = json_decode(file_get_contents('rulesets/rulesets.json'),true);
34 | $github = 'https://github.com/sakamies/css-cheats';
35 | $appCredits = '@sakamies / @workflower ';
36 | $reportIssue = 'Report an issue ';
37 | $createSet = 'Create a cheatsheet ';
38 |
39 | // If there is no name given, output the index list and die
40 | $setName = filter_input(INPUT_GET, 'name', FILTER_SANITIZE_STRING);
41 | if(isset($setName) == false){
42 | include('list.php');
43 | exit();
44 | }
45 |
46 | // If a name is in the url, make sure it exists in sets.json
47 | // Should be safe to use setName
48 | $setExists = array_key_exists($setName, $sets);
49 | if ($setExists == false) {
50 | header('HTTP/1.0 404 Not Found');
51 | include('error.php');
52 | exit();
53 | } else {
54 | // Ok cool, we have a cheatsheet, time party
55 | // Read page title and stuff from sets.json according to bundle
56 | $set = $sets[$setName];
57 | $title = $set['title'];
58 | $credits = creditsLinks($set['credits']);
59 | $specs = specsLinks($set['specs']);
60 | $helpText = $set['help-text'];
61 | include('app.php');
62 | }
63 |
64 | ?>
65 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-items_center.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-items_center
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-items_stretch.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-items_stretch
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-items_flex-end.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-items_flex-end
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/justify-content_center.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | justify-content_center
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-items_flex-start.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-items_flex-start
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/justify-content_flex-end.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | justify-content_flex-end
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/justify-content_flex-start.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | justify-content_flex-start
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/justify-content_space-around.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | justify-content_space-around
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/justify-content_space-between.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | justify-content_space-between
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-direction_column.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-direction_column
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-direction_column-reverse.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-direction_column-reverse
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-direction_row.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-direction_row
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-direction_row-reverse.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-direction_row-reverse
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-content_center.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-content_center
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-content_flex-end.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-content_flex-end
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-content_stretch.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-content_stretch
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-content_flex-start.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-content_flex-start
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-content_space-around.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-content_space-around
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-content_space-between.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-content_space-between
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/display_inline-flex.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | display_inline-flex
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-self_auto.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-self_auto
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/app.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flexbox Cheatsheet
6 |
7 |
8 |
9 |
10 |
11 |
38 |
42 |
43 |
44 |
{
45 |
46 |
47 |
48 | $value): ?>
49 |
50 |
51 | :
52 | ;
53 |
59 |
60 |
61 |
62 |
63 |
64 | }
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-self_flex-end.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-self_flex-end
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-self_flex-start.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-self_flex-start
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-self_stretch.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-self_stretch
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-grow_1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-grow_1
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-self_baseline.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-self_baseline
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/align-self_center.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | align-self_center
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-wrap_wrap.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-wrap_wrap
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-grow_0.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-grow_0
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-wrap_wrap-reverse.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-wrap_wrap-reverse
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-shrink_1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-shrink_1
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/flex-shrink_0.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | flex-shrink_0
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/rulesets/flexbox.cheats/fx-img/order_0.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | order_0
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/assets/js/jquery.hotkeys.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Hotkeys Plugin
3 | * Copyright 2010, John Resig
4 | * Dual licensed under the MIT or GPL Version 2 licenses.
5 | *
6 | * Based upon the plugin by Tzury Bar Yochay:
7 | * http://github.com/tzuryby/hotkeys
8 | *
9 | * Original idea by:
10 | * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
11 | */
12 |
13 | /*
14 | * One small change is: now keys are passed by object { keys: '...' }
15 | * Might be useful, when you want to pass some other data to your handler
16 | */
17 |
18 | (function(jQuery){
19 |
20 | jQuery.hotkeys = {
21 | version: "0.8",
22 |
23 | specialKeys: {
24 | 8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
25 | 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
26 | 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=",
27 | 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
28 | 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
29 | 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
30 | 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=",
31 | 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'"
32 | },
33 |
34 | shiftNums: {
35 | "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
36 | "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
37 | ".": ">", "/": "?", "\\": "|"
38 | },
39 |
40 | // excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url
41 | textAcceptingInputTypes: [
42 | "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime",
43 | "datetime-local", "search", "color", "tel"],
44 |
45 | options: {
46 | filterTextInputs: true
47 | }
48 | };
49 |
50 | function keyHandler( handleObj ) {
51 | if ( typeof handleObj.data === "string" ) {
52 | handleObj.data = { keys: handleObj.data };
53 | }
54 |
55 | // Only care when a possible input has been specified
56 | if ( !handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string" ) {
57 | return;
58 | }
59 |
60 | var origHandler = handleObj.handler,
61 | keys = handleObj.data.keys.toLowerCase().split(" ");
62 |
63 | handleObj.handler = function( event ) {
64 | // Don't fire in text-accepting inputs that we didn't directly bind to
65 | if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
66 | ( jQuery.hotkeys.options.filterTextInputs &&
67 | jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1 ) ) ) {
68 | return;
69 | }
70 |
71 | var special = jQuery.hotkeys.specialKeys[ event.keyCode ],
72 | character = String.fromCharCode( event.which ).toLowerCase(),
73 | modif = "", possible = {};
74 |
75 | jQuery.each([ "alt", "ctrl", "meta", "shift" ], function(index, specialKey) {
76 | if (event[specialKey + 'Key'] && special !== specialKey) {
77 | modif += specialKey + '+';
78 | }
79 | });
80 |
81 |
82 | modif = modif.replace('alt+ctrl+meta+shift', 'hyper');
83 |
84 | if ( special ) {
85 | possible[ modif + special ] = true;
86 | }
87 |
88 | if ( character ) {
89 | possible[ modif + character ] = true;
90 | possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
91 |
92 | // "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
93 | if ( modif === "shift+" ) {
94 | possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
95 | }
96 | }
97 |
98 | for ( var i = 0, l = keys.length; i < l; i++ ) {
99 | if ( possible[ keys[i] ] ) {
100 | return origHandler.apply( this, arguments );
101 | }
102 | }
103 | };
104 | }
105 |
106 | jQuery.each([ "keydown", "keyup", "keypress" ], function() {
107 | jQuery.event.special[ this ] = { add: keyHandler };
108 | });
109 |
110 | })( this.jQuery );
111 |
--------------------------------------------------------------------------------
/app/assets/scss/yogert.scss:
--------------------------------------------------------------------------------
1 | //Monokai colors:
2 |
3 | $dark: #272822;
4 | $light: #f8f8f2;
5 | $gray: #75715e;
6 | $red: #f92772;
7 | $purple: #be84ff;
8 | $green: #a6e22d;
9 | $yellow: #e6db74;
10 | $orange: #f6aa10;
11 | $blue: #66d9ef;
12 |
13 |
14 | *,
15 | *::before,
16 | *::after {
17 | box-sizing: border-box;
18 | }
19 |
20 | body {
21 | font-size: 16px;
22 | line-height: 25px;
23 | font-family: monospace;
24 | -webkit-font-smoothing: antialiased;
25 | margin: 0;
26 | padding: 0;
27 | color: $light;
28 | background: $gray;
29 | background: $dark;
30 | }
31 | body::after {
32 | content: '';
33 | display: table;
34 | clear: both;
35 | }
36 | a {
37 | color: $orange;
38 | }
39 | img,
40 | svg {
41 | vertical-align: middle;
42 | }
43 | h1 {
44 | font-size: 32px;
45 | line-height: 35px;
46 | margin: 25px 0 25px 0;
47 | }
48 | h2 {
49 | font-size: 24px;
50 | line-height: 25px;
51 | margin: 0 0 25px 0;
52 | }
53 | h1 + h2 {
54 | margin-top: -25px;
55 | }
56 | h3 {
57 | font-size: inherit;
58 | font-weight: bold;
59 | margin: 0 0 0px 0;
60 | }
61 | p {
62 | margin: 0px 0 12px 0;
63 | }
64 | ul {
65 | margin: 0 0 12px 0;
66 | padding: 0;
67 | list-style: none;
68 | list-style-position: outside;
69 | }
70 | li {
71 | margin: 0;
72 | padding: 0;
73 | }
74 |
75 | textarea {
76 | font-family: inherit;
77 | font-weight: inherit;
78 | font-size: inherit;
79 | line-height: inherit;
80 | -webkit-font-smoothing: inherit;
81 | }
82 | button {
83 | display: inline-block;
84 | vertical-align: middle;
85 | height: 25px;
86 | width: 25px;
87 | border-radius: 3px;
88 | border: none;
89 | color: $light;
90 | background: transparent;
91 | border: 1px solid;
92 | -webkit-font-smoothing: inherit;
93 | }
94 |
95 | $selfg: #fffff8;
96 | $selbg: rgba(lighten(#9D550F, 10%), .65);
97 | $selbg: $orange;
98 | ::selection {
99 | color: $selfg;
100 | background: $selbg;
101 | }
102 | ::-moz-selection {
103 | color: $selfg;
104 | background: $selbg;
105 | }
106 | $selfg: $dark;
107 | $selbg: rgba(desaturate(darken($blue, 20%), 10%), .35);
108 | textarea::selection {
109 | color: $selfg;
110 | background: $selbg;
111 | }
112 | textarea::-moz-selection {
113 | color: $selfg;
114 | background: $selbg;
115 | }
116 |
117 | :focus {
118 | outline: none;
119 | }
120 | .hide {
121 | display: none;
122 | }
123 |
124 | .layout {
125 | min-height: 100vh;
126 | display: flex;
127 | flex-direction: row;
128 | flex-wrap: wrap;
129 | align-items: flex-start;
130 | justify-content: flex-start;
131 | }
132 |
133 | .header {
134 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
135 | flex-shrink: 1;
136 | order: 99;
137 | width: 400px;
138 | align-self: stretch;
139 | padding: 0 25px 25px 25px;
140 | margin-left: auto;
141 | color: rgba($light, .7);
142 | border: 1px solid rgba($light, .2);
143 | border-width: 0px 0px 0px 1px;
144 | }
145 | @media (max-width: 1227px) {
146 | .header {
147 | order: 99;
148 | width: 100%;
149 | align-self: auto;
150 | border-width: 1px 0px 0px 0px;
151 | }
152 | }
153 | .help {
154 | margin: 25px 0 50px 0;
155 | }
156 |
157 | .rule {
158 | position: relative;
159 | flex-shrink: 0;
160 | max-width: 520px;
161 | padding: 25px 13px 25px 12px;
162 | margin: 0 12px;
163 | background: $dark;
164 | border-radius: 4px;
165 | }
166 | .selector {
167 | color: $green;
168 | cursor: pointer;
169 | }
170 | .row-group {
171 | }
172 | .row-group::after {
173 | content: '';
174 | display: block;
175 | margin-left: 20px;
176 | padding-bottom: 3px;
177 | border-bottom: 1px dotted rgba(255,255,255,.1);
178 | margin-bottom: 3px;
179 | }
180 | .row-group:last-child::after {
181 | /*display: none;*/
182 | }
183 | .declaration {
184 | line-height: 25px;
185 | white-space: nowrap;
186 | display: block;
187 | position: relative;
188 | padding-right: 66px;
189 | }
190 | .declaration.active {
191 | background: rgba(117, 113, 94, .2);
192 | border-radius: 2px;
193 | }
194 | .marker {
195 | color: $red;
196 | }
197 | .marker::before {
198 | position: absolute;
199 | top: 0;
200 | right: 100%;
201 | margin-right: -14px;
202 | white-space: pre;
203 | display: block;
204 | }
205 | .active .marker::before {
206 | display: inline-block;
207 | content: '●';
208 | }
209 | .property {
210 | color: $blue;
211 | }
212 | .property::before {
213 | white-space: pre;
214 | content: ' ';
215 | }
216 | .value {
217 | color: $blue;
218 | }
219 |
220 | .declaration svg {
221 | position: absolute;
222 | right: 2px;
223 | top: 50%;
224 | margin-top: -11px;
225 | opacity: .8;
226 | }
227 | .declaration.active svg {
228 | opacity: 1;
229 | }
230 | .declaration:not(.active) svg #selector {
231 | //fill: $light;
232 | }
233 |
234 | .copyboard {
235 | display: none;
236 | position: absolute;
237 | top: 13px;
238 | left: 0;
239 | right: 0;
240 | bottom: 12px;
241 | width: 100%;
242 | height: 100%;
243 | margin: 0;
244 | padding: 12px 13px 13px 12px;
245 | color: $dark;
246 | background: $light;
247 | border: none;
248 | border-radius: 3px;
249 | }
250 | .overlay {
251 | display: none;
252 | position: fixed;
253 | top: 0;
254 | left: 0;
255 | right: 0;
256 | bottom: 0;
257 | }
258 |
--------------------------------------------------------------------------------
/app/assets/css/yogert.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | *,
3 | *::before,
4 | *::after {
5 | box-sizing: border-box; }
6 |
7 | body {
8 | font-size: 16px;
9 | line-height: 25px;
10 | font-family: monospace;
11 | -webkit-font-smoothing: antialiased;
12 | margin: 0;
13 | padding: 0;
14 | color: #f8f8f2;
15 | background: #75715e;
16 | background: #272822; }
17 |
18 | body::after {
19 | content: '';
20 | display: table;
21 | clear: both; }
22 |
23 | a {
24 | color: #f6aa10; }
25 |
26 | img,
27 | svg {
28 | vertical-align: middle; }
29 |
30 | h1 {
31 | font-size: 32px;
32 | line-height: 35px;
33 | margin: 25px 0 25px 0; }
34 |
35 | h2 {
36 | font-size: 24px;
37 | line-height: 25px;
38 | margin: 0 0 25px 0; }
39 |
40 | h1 + h2 {
41 | margin-top: -25px; }
42 |
43 | h3 {
44 | font-size: inherit;
45 | font-weight: bold;
46 | margin: 0 0 0px 0; }
47 |
48 | p {
49 | margin: 0px 0 12px 0; }
50 |
51 | ul {
52 | margin: 0 0 12px 0;
53 | padding: 0;
54 | list-style: none;
55 | list-style-position: outside; }
56 |
57 | li {
58 | margin: 0;
59 | padding: 0; }
60 |
61 | textarea {
62 | font-family: inherit;
63 | font-weight: inherit;
64 | font-size: inherit;
65 | line-height: inherit;
66 | -webkit-font-smoothing: inherit; }
67 |
68 | button {
69 | display: inline-block;
70 | vertical-align: middle;
71 | height: 25px;
72 | width: 25px;
73 | border-radius: 3px;
74 | border: none;
75 | color: #f8f8f2;
76 | background: transparent;
77 | border: 1px solid;
78 | -webkit-font-smoothing: inherit; }
79 |
80 | ::-moz-selection {
81 | color: #fffff8;
82 | background: #f6aa10; }
83 |
84 | ::selection {
85 | color: #fffff8;
86 | background: #f6aa10; }
87 |
88 | ::-moz-selection {
89 | color: #fffff8;
90 | background: #f6aa10; }
91 |
92 | textarea::-moz-selection {
93 | color: #272822;
94 | background: rgba(35, 177, 204, 0.35); }
95 |
96 | textarea::selection {
97 | color: #272822;
98 | background: rgba(35, 177, 204, 0.35); }
99 |
100 | textarea::-moz-selection {
101 | color: #272822;
102 | background: rgba(35, 177, 204, 0.35); }
103 |
104 | :focus {
105 | outline: none; }
106 |
107 | .hide {
108 | display: none; }
109 |
110 | .layout {
111 | min-height: 100vh;
112 | display: -webkit-box;
113 | display: -ms-flexbox;
114 | display: flex;
115 | -webkit-box-orient: horizontal;
116 | -webkit-box-direction: normal;
117 | -ms-flex-direction: row;
118 | flex-direction: row;
119 | -ms-flex-wrap: wrap;
120 | flex-wrap: wrap;
121 | -webkit-box-align: start;
122 | -ms-flex-align: start;
123 | align-items: flex-start;
124 | -webkit-box-pack: start;
125 | -ms-flex-pack: start;
126 | justify-content: flex-start; }
127 |
128 | .header {
129 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
130 | -ms-flex-negative: 1;
131 | flex-shrink: 1;
132 | -webkit-box-ordinal-group: 100;
133 | -ms-flex-order: 99;
134 | order: 99;
135 | width: 400px;
136 | -ms-flex-item-align: stretch;
137 | align-self: stretch;
138 | padding: 0 25px 25px 25px;
139 | margin-left: auto;
140 | color: rgba(248, 248, 242, 0.7);
141 | border: 1px solid rgba(248, 248, 242, 0.2);
142 | border-width: 0px 0px 0px 1px; }
143 |
144 | @media (max-width: 1227px) {
145 | .header {
146 | -webkit-box-ordinal-group: 100;
147 | -ms-flex-order: 99;
148 | order: 99;
149 | width: 100%;
150 | -ms-flex-item-align: auto;
151 | align-self: auto;
152 | border-width: 1px 0px 0px 0px; } }
153 |
154 | .help {
155 | margin: 25px 0 50px 0; }
156 |
157 | .rule {
158 | position: relative;
159 | -ms-flex-negative: 0;
160 | flex-shrink: 0;
161 | max-width: 520px;
162 | padding: 25px 13px 25px 12px;
163 | margin: 0 12px;
164 | background: #272822;
165 | border-radius: 4px; }
166 |
167 | .selector {
168 | color: #a6e22d;
169 | cursor: pointer; }
170 |
171 | .row-group::after {
172 | content: '';
173 | display: block;
174 | margin-left: 20px;
175 | padding-bottom: 3px;
176 | border-bottom: 1px dotted rgba(255, 255, 255, 0.1);
177 | margin-bottom: 3px; }
178 |
179 | .row-group:last-child::after {
180 | /*display: none;*/ }
181 |
182 | .declaration {
183 | line-height: 25px;
184 | white-space: nowrap;
185 | display: block;
186 | position: relative;
187 | padding-right: 66px; }
188 |
189 | .declaration.active {
190 | background: rgba(117, 113, 94, 0.2);
191 | border-radius: 2px; }
192 |
193 | .marker {
194 | color: #f92772; }
195 |
196 | .marker::before {
197 | position: absolute;
198 | top: 0;
199 | right: 100%;
200 | margin-right: -14px;
201 | white-space: pre;
202 | display: block; }
203 |
204 | .active .marker::before {
205 | display: inline-block;
206 | content: '●'; }
207 |
208 | .property {
209 | color: #66d9ef; }
210 |
211 | .property::before {
212 | white-space: pre;
213 | content: ' '; }
214 |
215 | .value {
216 | color: #66d9ef; }
217 |
218 | .declaration svg {
219 | position: absolute;
220 | right: 2px;
221 | top: 50%;
222 | margin-top: -11px;
223 | opacity: .8; }
224 |
225 | .declaration.active svg {
226 | opacity: 1; }
227 |
228 | .copyboard {
229 | display: none;
230 | position: absolute;
231 | top: 13px;
232 | left: 0;
233 | right: 0;
234 | bottom: 12px;
235 | width: 100%;
236 | height: 100%;
237 | margin: 0;
238 | padding: 12px 13px 13px 12px;
239 | color: #272822;
240 | background: #f8f8f2;
241 | border: none;
242 | border-radius: 3px; }
243 |
244 | .overlay {
245 | display: none;
246 | position: fixed;
247 | top: 0;
248 | left: 0;
249 | right: 0;
250 | bottom: 0; }
251 |
--------------------------------------------------------------------------------
/app/assets/js/fragment.js:
--------------------------------------------------------------------------------
1 | ;(function(win, doc) {
2 |
3 | // Gets either a string, which it will just return, or a {html, json} pair which
4 | // it will try to render with Mustache, Handlebars and Underscore.
5 | // If that fails, it just returns the html.
6 | var render = function(html, json) {
7 | if (typeof json === "undefined") {
8 | return html;
9 | }
10 |
11 | if (typeof win.Mustache !== "undefined" &&
12 | typeof win.Mustache.render !== "undefined") {
13 | return Mustache.render(html, json);
14 | } else if (typeof win.Handlebars !== "undefined" &&
15 | typeof win.Handlebars.compile !== "undefined") {
16 | return Handlebars.compile(html)(json);
17 | } else if (typeof win._ !== "undefined" &&
18 | typeof win._.template !== "undefined") {
19 | return output = _.template(html, json);
20 | }
21 |
22 | return html;
23 | };
24 |
25 | // Helper function to load ajax data
26 | var load_xhr = function(url, callback) {
27 | var request = new XMLHttpRequest();
28 | request.open('GET', url);
29 | request.send();
30 | request.onload = function() {
31 | callback(this.response);
32 | };
33 | };
34 |
35 | // Helper function to load jsonp data
36 | var load_jsonp = function(url, callback, url_parser) {
37 | var script = doc.createElement('script');
38 | script.src = url + (parser.search == '' ? '?' : '&') +
39 | fragment.jsonp + '=JSONPCallback';
40 |
41 | win.JSONPCallback = function(data) {
42 | // The callback function expects a string
43 | callback(JSON.stringify(data));
44 | win.JSONPCallback = null;
45 | // Clean up DOM by removing the JSONP script element
46 | var parent = script.parentNode;
47 | if (parent) {
48 | parent.removeChild(script);
49 | }
50 | script = null;
51 | }
52 | doc.getElementsByTagName('head')[0].appendChild(script);
53 | };
54 |
55 | var load = function(url, callback) {
56 | // We'll need something that can easily parse urls
57 | var url_parser = doc.createElement('a');
58 | url_parser.href = url;
59 |
60 | // If the resource is located at the same hostname, assume ajax
61 | if (url_parser.hostname == win.location.hostname) {
62 | load_xhr(url, callback);
63 | }
64 | // If the resource is located at a different hostname, assume jsonp
65 | else {
66 | load_jsonp(url, callback, url_parser);
67 | }
68 | };
69 |
70 | var render_template = function(element, html, json) {
71 | var context = extend(JSON.parse(json), context);
72 | element.innerHTML = fragment.render(html, context);
73 | evaluate(element, context);
74 | };
75 |
76 | var render_html = function(element, html) {
77 | var context = this.context;
78 |
79 | // If the innerHTML is nonempty: the context is interpreted as the
80 | // combination of the JSONified innerHTML and the existing context.
81 | // The JSONified innerHTML has a higher precedence over the existing context.
82 | if (element.innerHTML != "") {
83 | context = extend(JSON.parse(element.innerHTML), context);
84 | }
85 |
86 | element.innerHTML = fragment.render(html, context);
87 | evaluate(element, context);
88 | };
89 |
90 | var render_json = function(element, json) {
91 | var context = extend(JSON.parse(json), context);
92 | element.innerHTML = fragment.render(element.innerHTML, context);
93 | evaluate(element, this.context);
94 | };
95 |
96 | // Handle an individual fragment
97 | var render_fragment = function(fragment_type, element) {
98 | var html_url = element.getAttribute('data-'+fragment.html);
99 | var json_url = element.getAttribute('data-'+fragment.json);
100 | var media = element.getAttribute('data-fragment-media');
101 |
102 | // Don't load anything if the media query doesn't match
103 | if ( media && win.matchMedia && !win.matchMedia(media).matches ) return;
104 |
105 | // Update the num_fragments and deligate rendering to a submethod
106 | var resource_loaded = function(render_handler) {
107 | render_handler();
108 | update_num_fragments(-1);
109 | };
110 |
111 | update_num_fragments(1);
112 |
113 | if (fragment_type.html && fragment_type.json) {
114 | load(html_url, function(html) {
115 | load(json_url, function(json) {
116 | resource_loaded(render_template.bind(this, element, html, json));
117 | });
118 | });
119 | }
120 | else if (fragment_type.html) {
121 | load(html_url, function(html) {
122 | resource_loaded(render_html.bind(this, element, html));
123 | });
124 | }
125 | else if (fragment_type.json) {
126 | load(json_url, function(json) {
127 | resource_loaded(render_json.bind(this, element, json));
128 | });
129 | }
130 | };
131 |
132 | var evaluate = function(parent, context) {
133 | if (typeof parent === "undefined" || !("querySelectorAll" in parent)) {
134 | parent = doc;
135 | }
136 |
137 | // Scope contains information for recursively rendering fragments
138 | var scope = { parent: parent, context: context };
139 | var fragments = parent.querySelectorAll('[data-'+fragment.html+'][data-'+fragment.json+']');
140 | Array.prototype.forEach.call(fragments, render_fragment.bind(scope, { json: true, html: true }));
141 |
142 | var fragments = parent.querySelectorAll('[data-'+fragment.html+']:not([data-'+fragment.json+'])');
143 | Array.prototype.forEach.call(fragments, render_fragment.bind(scope, { json: false, html: true }));
144 |
145 | var fragments = parent.querySelectorAll('[data-'+fragment.json+']:not([data-'+fragment.html+'])');
146 | Array.prototype.forEach.call(fragments, render_fragment.bind(scope, { json: true, html: false }));
147 | };
148 |
149 | var extend = function(obj, defaults) {
150 | if (typeof obj === "undefined") obj = {};
151 | for (var element in defaults) {
152 | if (!obj.hasOwnProperty(element)) {
153 | obj[element] = defaults[element];
154 | }
155 | }
156 | return obj;
157 | };
158 |
159 | var num_fragments = 0;
160 | var max_fragments = 0;
161 | var update_num_fragments = function(diff) {
162 | num_fragments += diff;
163 |
164 | if (num_fragments > max_fragments) {
165 | max_fragments = num_fragments;
166 | }
167 | if (num_fragments == 0) {
168 | fragment.ready(max_fragments);
169 | }
170 | };
171 |
172 | // Extend fragment with defaults
173 | var fragment = extend(win.fragment, {
174 | html: 'fragment',
175 | json: 'fragment-json',
176 | jsonp: 'callback',
177 | manual: false,
178 | render: render,
179 | evaluate: evaluate,
180 | ready: function(){}
181 | });
182 |
183 | // Autoload
184 | if (!fragment.manual) {
185 | doc.addEventListener('DOMContentLoaded', function() {
186 | fragment.evaluate();
187 | });
188 | }
189 |
190 | // Just overwrite any existing "fragment" property
191 | win.fragment = fragment;
192 |
193 | })(window, window.document);
194 |
--------------------------------------------------------------------------------
/app/assets/js/yogert.js:
--------------------------------------------------------------------------------
1 | fragment = {
2 | ready: function() {
3 | $(document).trigger('ready.fragment');
4 | }
5 | };
6 |
7 | jQuery.fn.selectText = function(){
8 | var doc = document;
9 | var element = this[0];
10 | var range, selection;
11 |
12 | if (doc.body.createTextRange) {
13 | range = document.body.createTextRange();
14 | range.moveToElementText(element);
15 | range.select();
16 | } else if (window.getSelection) {
17 | selection = window.getSelection();
18 | range = document.createRange();
19 | range.selectNodeContents(element);
20 | selection.removeAllRanges();
21 | selection.addRange(range);
22 | }
23 | };
24 |
25 |
26 | $(document).on('ready.fragment', function(event) {
27 |
28 | console.log('fragments loaded');
29 |
30 | //TODO: Ohh screw timeout, why wont the fragments loaded work?
31 | setTimeout(function () {
32 |
33 |
34 | var selectable = '.declaration, .value';
35 | $(selectable).attr('tabindex', '1');
36 |
37 | $(selectable).on('focus', function(event) {
38 | var decl = $(this).closest('.declaration');
39 |
40 | decl.addClass('active');
41 | decl.siblings().removeClass('active');
42 |
43 | $('.focus').removeClass('focus');
44 | $(this).addClass('focus');
45 | setTimeout(function () {
46 | $('.focus').selectText();
47 | }, 0);
48 | });
49 | $(selectable).on('mouseup click', function(event) {
50 | event.preventDefault();
51 | event.stopPropagation();
52 | });
53 | $(selectable).on('mousedown', function(event) {
54 | event.preventDefault();
55 | event.stopPropagation();
56 | $(this).focus();
57 | });
58 |
59 | $('.marker').on('click', function(event) {
60 | event.preventDefault();
61 | event.stopPropagation();
62 | $(this).closest('.declaration').removeClass('active');
63 | $(this).selectText();
64 | });
65 |
66 | $('.selector').on('click', function(event) {
67 | event.preventDefault();
68 | var rule = $(this).closest('.rule');
69 | var copyboard = rule.find('.copyboard');
70 | var selector = rule.find('.selector');
71 | var declarations = rule.find('.declaration.active');
72 | var cssText = '';
73 |
74 | declarations = declarations.clone();
75 | declarations.find('svg').remove();
76 | console.log(declarations);
77 | cssText = selector.text() + ' {';
78 | cssText += declarations.text();
79 | cssText += '}';
80 | cssText = S(cssText);
81 | cssText = cssText
82 | .replaceAll(' ', '')
83 | .replaceAll('\n', '')
84 | .replaceAll('{', ' {\n ')
85 | .replaceAll(':', ': ')
86 | .replaceAll(';', ';\n ')
87 | .replaceAll(' }', '}');
88 | copyboard.val(cssText.s).addClass('show').show().select();
89 | $('.overlay').show();
90 | });
91 |
92 |
93 | $('.declaration').bind('keydown', 'up', function(event) {
94 | event.preventDefault();
95 | event.stopPropagation();
96 | var $this = $(this);
97 | var prev = $this.prev();
98 | if (prev.length === 0) { return; }
99 | $this.removeClass('active');
100 | prev.focus();
101 | });
102 | $('.value').bind('keydown', 'up', function(event) {
103 | event.preventDefault();
104 | event.stopPropagation();
105 | var $this = $(this);
106 | var decl = $this.closest('.declaration');
107 | var prev = decl.prev();
108 | if (prev.length === 0) { return; }
109 | var prevValue = prev.find('.value');
110 | prev.removeClass('active');
111 | prevValue.focus();
112 | });
113 | $('.declaration').bind('keydown', 'down', function(event) {
114 | event.preventDefault();
115 | event.stopPropagation();
116 | var $this = $(this);
117 | var next = $this.next();
118 | if (next.length === 0) { return; }
119 | $this.removeClass('active');
120 | next.focus();
121 | });
122 | $('.value').bind('keydown', 'down', function(event) {
123 | event.preventDefault();
124 | event.stopPropagation();
125 | var $this = $(this);
126 | var decl = $this.closest('.declaration');
127 | var next = decl.next();
128 | if (next.length === 0) { return; }
129 | var nextValue = next.find('.value');
130 | next.removeClass('active');
131 | nextValue.focus();
132 | });
133 | $('.declaration').bind('keydown', 'right', function(event) {
134 | event.preventDefault();
135 | event.stopPropagation();
136 | $(this).find('.value').focus();
137 | });
138 | $('.value').bind('keydown', 'left', function(event) {
139 | event.preventDefault();
140 | event.stopPropagation();
141 | $(this).closest('.declaration').focus();
142 | });
143 | $('.declaration, .value').bind('keydown', 'tab space', function(event) {
144 | event.preventDefault();
145 | event.stopPropagation();
146 |
147 | var nextGroup;
148 | var next;
149 |
150 | var spaceKey = event.which === 32;
151 | if (spaceKey) {
152 | $(this).closest('.declaration').removeClass('active');
153 | }
154 |
155 | nextGroup = $(this).closest('.row-group').next('.row-group');
156 | if (nextGroup.length === 0) {
157 | nextGroup = $(this).closest('.rule').next('.rule').find('.row-group:first');
158 | }
159 | if (nextGroup.length === 0) {
160 | nextGroup = $(this).closest('.rules').find('.rule:first .row-group:first');
161 | }
162 |
163 | next = nextGroup.find('.active:first');
164 | if (next.length === 0) {
165 | nextGroup.find('.declaration:first').focus();
166 | } else {
167 | next.focus();
168 | }
169 | });
170 | $('.declaration, .value').bind('keydown', 'shift+tab', function(event) {
171 | event.preventDefault();
172 | event.stopPropagation();
173 |
174 | var prevGroup;
175 | var prev;
176 |
177 | prevGroup = $(this).closest('.row-group').prev('.row-group');
178 | console.log('1',prevGroup[0]);
179 | if (prevGroup.length === 0) {
180 | console.log($(this).closest('.rule'));
181 | prevGroup = $(this).closest('.rule').prev('.rule').find('.row-group:last');
182 | }
183 | if (prevGroup.length === 0) {
184 | prevGroup = $(this).closest('.rules').find('.rule:last .row-group:last');
185 | }
186 |
187 | prev = prevGroup.find('.active:first');
188 | if (prev.length === 0) {
189 | prevGroup.find('.declaration:first').focus();
190 | } else {
191 | prev.focus();
192 | }
193 | });
194 |
195 | $('.copyboard').on('copy', function(event) {
196 | setTimeout(function () {
197 | $('.copyboard.show').removeClass('show').hide();
198 | }, 0);
199 | });
200 | $('.copyboard').on('keydown', 'esc', function(event) {
201 | event.preventDefault();
202 | $(this).hide();
203 | });
204 | $('.overlay').on('click', function(event) {
205 | event.preventDefault();
206 | $('.overlay, .copyboard.show').removeClass('show').hide();
207 | });
208 |
209 | }, 500);
210 |
211 | });
212 |
--------------------------------------------------------------------------------
/app/assets/js/string.js:
--------------------------------------------------------------------------------
1 | /*
2 | string.js - Copyright (C) 2012-2014, JP Richardson
3 | */
4 |
5 | !(function() {
6 | "use strict";
7 |
8 | var VERSION = '1.9.0';
9 |
10 | var ENTITIES = {};
11 |
12 | //******************************************************************************
13 | // Added an initialize function which is essentially the code from the S
14 | // constructor. Now, the S constructor calls this and a new method named
15 | // setValue calls it as well. The setValue function allows constructors for
16 | // modules that extend string.js to set the initial value of an object without
17 | // knowing the internal workings of string.js.
18 | //
19 | // Also, all methods which return a new S object now call:
20 | //
21 | // return new this.constructor(s);
22 | //
23 | // instead of:
24 | //
25 | // return new S(s);
26 | //
27 | // This allows extended objects to keep their proper instanceOf and constructor.
28 | //******************************************************************************
29 |
30 | function initialize (object, s) {
31 | if (s !== null && s !== undefined) {
32 | if (typeof s === 'string')
33 | object.s = s;
34 | else
35 | object.s = s.toString();
36 | } else {
37 | object.s = s; //null or undefined
38 | }
39 |
40 | object.orig = s; //original object, currently only used by toCSV() and toBoolean()
41 |
42 | if (s !== null && s !== undefined) {
43 | if (object.__defineGetter__) {
44 | object.__defineGetter__('length', function() {
45 | return object.s.length;
46 | })
47 | } else {
48 | object.length = s.length;
49 | }
50 | } else {
51 | object.length = -1;
52 | }
53 | }
54 |
55 | function S(s) {
56 | initialize(this, s);
57 | }
58 |
59 | var __nsp = String.prototype;
60 | var __sp = S.prototype = {
61 |
62 | between: function(left, right) {
63 | var s = this.s;
64 | var startPos = s.indexOf(left);
65 | var endPos = s.indexOf(right, startPos + left.length);
66 | if (endPos == -1 && right != null)
67 | return new this.constructor('')
68 | else if (endPos == -1 && right == null)
69 | return new this.constructor(s.substring(startPos + left.length))
70 | else
71 | return new this.constructor(s.slice(startPos + left.length, endPos));
72 | },
73 |
74 | //# modified slightly from https://github.com/epeli/underscore.string
75 | camelize: function() {
76 | var s = this.trim().s.replace(/(\-|_|\s)+(.)?/g, function(mathc, sep, c) {
77 | return (c ? c.toUpperCase() : '');
78 | });
79 | return new this.constructor(s);
80 | },
81 |
82 | capitalize: function() {
83 | return new this.constructor(this.s.substr(0, 1).toUpperCase() + this.s.substring(1).toLowerCase());
84 | },
85 |
86 | charAt: function(index) {
87 | return this.s.charAt(index);
88 | },
89 |
90 | chompLeft: function(prefix) {
91 | var s = this.s;
92 | if (s.indexOf(prefix) === 0) {
93 | s = s.slice(prefix.length);
94 | return new this.constructor(s);
95 | } else {
96 | return this;
97 | }
98 | },
99 |
100 | chompRight: function(suffix) {
101 | if (this.endsWith(suffix)) {
102 | var s = this.s;
103 | s = s.slice(0, s.length - suffix.length);
104 | return new this.constructor(s);
105 | } else {
106 | return this;
107 | }
108 | },
109 |
110 | //#thanks Google
111 | collapseWhitespace: function() {
112 | var s = this.s.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, '');
113 | return new this.constructor(s);
114 | },
115 |
116 | contains: function(ss) {
117 | return this.s.indexOf(ss) >= 0;
118 | },
119 |
120 | count: function(ss) {
121 | var count = 0
122 | , pos = this.s.indexOf(ss)
123 |
124 | while (pos >= 0) {
125 | count += 1
126 | pos = this.s.indexOf(ss, pos + 1)
127 | }
128 |
129 | return count
130 | },
131 |
132 | //#modified from https://github.com/epeli/underscore.string
133 | dasherize: function() {
134 | var s = this.trim().s.replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase();
135 | return new this.constructor(s);
136 | },
137 |
138 | decodeHtmlEntities: function() { //https://github.com/substack/node-ent/blob/master/index.js
139 | var s = this.s;
140 | s = s.replace(/(\d+);?/g, function (_, code) {
141 | return String.fromCharCode(code);
142 | })
143 | .replace(/[xX]([A-Fa-f0-9]+);?/g, function (_, hex) {
144 | return String.fromCharCode(parseInt(hex, 16));
145 | })
146 | .replace(/&([^;\W]+;?)/g, function (m, e) {
147 | var ee = e.replace(/;$/, '');
148 | var target = ENTITIES[e] || (e.match(/;$/) && ENTITIES[ee]);
149 |
150 | if (typeof target === 'number') {
151 | return String.fromCharCode(target);
152 | }
153 | else if (typeof target === 'string') {
154 | return target;
155 | }
156 | else {
157 | return m;
158 | }
159 | })
160 |
161 | return new this.constructor(s);
162 | },
163 |
164 | endsWith: function(suffix) {
165 | var l = this.s.length - suffix.length;
166 | return l >= 0 && this.s.indexOf(suffix, l) === l;
167 | },
168 |
169 | escapeHTML: function() { //from underscore.string
170 | return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }));
171 | },
172 |
173 | ensureLeft: function(prefix) {
174 | var s = this.s;
175 | if (s.indexOf(prefix) === 0) {
176 | return this;
177 | } else {
178 | return new this.constructor(prefix + s);
179 | }
180 | },
181 |
182 | ensureRight: function(suffix) {
183 | var s = this.s;
184 | if (this.endsWith(suffix)) {
185 | return this;
186 | } else {
187 | return new this.constructor(s + suffix);
188 | }
189 | },
190 |
191 | humanize: function() { //modified from underscore.string
192 | if (this.s === null || this.s === undefined)
193 | return new this.constructor('')
194 | var s = this.underscore().replace(/_id$/,'').replace(/_/g, ' ').trim().capitalize()
195 | return new this.constructor(s)
196 | },
197 |
198 | isAlpha: function() {
199 | return !/[^a-z\xDF-\xFF]/.test(this.s.toLowerCase());
200 | },
201 |
202 | isAlphaNumeric: function() {
203 | return !/[^0-9a-z\xDF-\xFF]/.test(this.s.toLowerCase());
204 | },
205 |
206 | isEmpty: function() {
207 | return this.s === null || this.s === undefined ? true : /^[\s\xa0]*$/.test(this.s);
208 | },
209 |
210 | isLower: function() {
211 | return this.isAlpha() && this.s.toLowerCase() === this.s;
212 | },
213 |
214 | isNumeric: function() {
215 | return !/[^0-9]/.test(this.s);
216 | },
217 |
218 | isUpper: function() {
219 | return this.isAlpha() && this.s.toUpperCase() === this.s;
220 | },
221 |
222 | left: function(N) {
223 | if (N >= 0) {
224 | var s = this.s.substr(0, N);
225 | return new this.constructor(s);
226 | } else {
227 | return this.right(-N);
228 | }
229 | },
230 |
231 | lines: function() { //convert windows newlines to unix newlines then convert to an Array of lines
232 | return this.replaceAll('\r\n', '\n').s.split('\n');
233 | },
234 |
235 | pad: function(len, ch) { //https://github.com/component/pad
236 | if (ch == null) ch = ' ';
237 | if (this.s.length >= len) return new this.constructor(this.s);
238 | len = len - this.s.length;
239 | var left = Array(Math.ceil(len / 2) + 1).join(ch);
240 | var right = Array(Math.floor(len / 2) + 1).join(ch);
241 | return new this.constructor(left + this.s + right);
242 | },
243 |
244 | padLeft: function(len, ch) { //https://github.com/component/pad
245 | if (ch == null) ch = ' ';
246 | if (this.s.length >= len) return new this.constructor(this.s);
247 | return new this.constructor(Array(len - this.s.length + 1).join(ch) + this.s);
248 | },
249 |
250 | padRight: function(len, ch) { //https://github.com/component/pad
251 | if (ch == null) ch = ' ';
252 | if (this.s.length >= len) return new this.constructor(this.s);
253 | return new this.constructor(this.s + Array(len - this.s.length + 1).join(ch));
254 | },
255 |
256 | parseCSV: function(delimiter, qualifier, escape, lineDelimiter) { //try to parse no matter what
257 | delimiter = delimiter || ',';
258 | escape = escape || '\\'
259 | if (typeof qualifier == 'undefined')
260 | qualifier = '"';
261 |
262 | var i = 0, fieldBuffer = [], fields = [], len = this.s.length, inField = false, inUnqualifiedString = false, self = this;
263 | var ca = function(i){return self.s.charAt(i)};
264 | if (typeof lineDelimiter !== 'undefined') var rows = [];
265 |
266 | if (!qualifier)
267 | inField = true;
268 |
269 | while (i < len) {
270 | var current = ca(i);
271 | switch (current) {
272 | case escape:
273 | //fix for issues #32 and #35
274 | if (inField && ((escape !== qualifier) || ca(i+1) === qualifier)) {
275 | i += 1;
276 | fieldBuffer.push(ca(i));
277 | break;
278 | }
279 | if (escape !== qualifier) break;
280 | case qualifier:
281 | inField = !inField;
282 | break;
283 | case delimiter:
284 | if(inUnqualifiedString) {
285 | inField=false;
286 | inUnqualifiedString=false;
287 | }
288 | if (inField && qualifier)
289 | fieldBuffer.push(current);
290 | else {
291 | fields.push(fieldBuffer.join(''))
292 | fieldBuffer.length = 0;
293 | }
294 | break;
295 | case lineDelimiter:
296 | if(inUnqualifiedString) {
297 | inField=false;
298 | inUnqualifiedString=false;
299 | fields.push(fieldBuffer.join(''))
300 | rows.push(fields);
301 | fields = [];
302 | fieldBuffer.length = 0;
303 | }
304 | else if (inField) {
305 | fieldBuffer.push(current);
306 | } else {
307 | if (rows) {
308 | fields.push(fieldBuffer.join(''))
309 | rows.push(fields);
310 | fields = [];
311 | fieldBuffer.length = 0;
312 | }
313 | }
314 | break;
315 | case ' ':
316 | if (inField)
317 | fieldBuffer.push(current);
318 | break;
319 | default:
320 | if (inField)
321 | fieldBuffer.push(current);
322 | else if(current!==qualifier) {
323 | fieldBuffer.push(current);
324 | inField=true;
325 | inUnqualifiedString=true;
326 | }
327 | break;
328 | }
329 | i += 1;
330 | }
331 |
332 | fields.push(fieldBuffer.join(''));
333 | if (rows) {
334 | rows.push(fields);
335 | return rows;
336 | }
337 | return fields;
338 | },
339 |
340 | replaceAll: function(ss, r) {
341 | //var s = this.s.replace(new RegExp(ss, 'g'), r);
342 | var s = this.s.split(ss).join(r)
343 | return new this.constructor(s);
344 | },
345 |
346 | right: function(N) {
347 | if (N >= 0) {
348 | var s = this.s.substr(this.s.length - N, N);
349 | return new this.constructor(s);
350 | } else {
351 | return this.left(-N);
352 | }
353 | },
354 |
355 | setValue: function (s) {
356 | initialize(this, s);
357 | return this;
358 | },
359 |
360 | slugify: function() {
361 | var sl = (new S(this.s.replace(/[^\w\s-]/g, '').toLowerCase())).dasherize().s;
362 | if (sl.charAt(0) === '-')
363 | sl = sl.substr(1);
364 | return new this.constructor(sl);
365 | },
366 |
367 | startsWith: function(prefix) {
368 | return this.s.lastIndexOf(prefix, 0) === 0;
369 | },
370 |
371 | stripPunctuation: function() {
372 | //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,""));
373 | return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " "));
374 | },
375 |
376 | stripTags: function() { //from sugar.js
377 | var s = this.s, args = arguments.length > 0 ? arguments : [''];
378 | multiArgs(args, function(tag) {
379 | s = s.replace(RegExp('<\/?' + tag + '[^<>]*>', 'gi'), '');
380 | });
381 | return new this.constructor(s);
382 | },
383 |
384 | template: function(values, opening, closing) {
385 | var s = this.s
386 | var opening = opening || Export.TMPL_OPEN
387 | var closing = closing || Export.TMPL_CLOSE
388 |
389 | var open = opening.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
390 | var close = closing.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$')
391 | var r = new RegExp(open + '(.+?)' + close, 'g')
392 | //, r = /\{\{(.+?)\}\}/g
393 | var matches = s.match(r) || [];
394 |
395 | matches.forEach(function(match) {
396 | var key = match.substring(opening.length, match.length - closing.length);//chop {{ and }}
397 | if (typeof values[key] != 'undefined')
398 | s = s.replace(match, values[key]);
399 | });
400 | return new this.constructor(s);
401 | },
402 |
403 | times: function(n) {
404 | return new this.constructor(new Array(n + 1).join(this.s));
405 | },
406 |
407 | toBoolean: function() {
408 | if (typeof this.orig === 'string') {
409 | var s = this.s.toLowerCase();
410 | return s === 'true' || s === 'yes' || s === 'on' || s === '1';
411 | } else
412 | return this.orig === true || this.orig === 1;
413 | },
414 |
415 | toFloat: function(precision) {
416 | var num = parseFloat(this.s)
417 | if (precision)
418 | return parseFloat(num.toFixed(precision))
419 | else
420 | return num
421 | },
422 |
423 | toInt: function() { //thanks Google
424 | // If the string starts with '0x' or '-0x', parse as hex.
425 | return /^\s*-?0x/i.test(this.s) ? parseInt(this.s, 16) : parseInt(this.s, 10)
426 | },
427 |
428 | trim: function() {
429 | var s;
430 | if (typeof __nsp.trim === 'undefined')
431 | s = this.s.replace(/(^\s*|\s*$)/g, '')
432 | else
433 | s = this.s.trim()
434 | return new this.constructor(s);
435 | },
436 |
437 | trimLeft: function() {
438 | var s;
439 | if (__nsp.trimLeft)
440 | s = this.s.trimLeft();
441 | else
442 | s = this.s.replace(/(^\s*)/g, '');
443 | return new this.constructor(s);
444 | },
445 |
446 | trimRight: function() {
447 | var s;
448 | if (__nsp.trimRight)
449 | s = this.s.trimRight();
450 | else
451 | s = this.s.replace(/\s+$/, '');
452 | return new this.constructor(s);
453 | },
454 |
455 | truncate: function(length, pruneStr) { //from underscore.string, author: github.com/rwz
456 | var str = this.s;
457 |
458 | length = ~~length;
459 | pruneStr = pruneStr || '...';
460 |
461 | if (str.length <= length) return new this.constructor(str);
462 |
463 | var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },
464 | template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'
465 |
466 | if (template.slice(template.length-2).match(/\w\w/))
467 | template = template.replace(/\s*\S+$/, '');
468 | else
469 | template = new S(template.slice(0, template.length-1)).trimRight().s;
470 |
471 | return (template+pruneStr).length > str.length ? new S(str) : new S(str.slice(0, template.length)+pruneStr);
472 | },
473 |
474 | toCSV: function() {
475 | var delim = ',', qualifier = '"', escape = '\\', encloseNumbers = true, keys = false;
476 | var dataArray = [];
477 |
478 | function hasVal(it) {
479 | return it !== null && it !== '';
480 | }
481 |
482 | if (typeof arguments[0] === 'object') {
483 | delim = arguments[0].delimiter || delim;
484 | delim = arguments[0].separator || delim;
485 | qualifier = arguments[0].qualifier || qualifier;
486 | encloseNumbers = !!arguments[0].encloseNumbers;
487 | escape = arguments[0].escape || escape;
488 | keys = !!arguments[0].keys;
489 | } else if (typeof arguments[0] === 'string') {
490 | delim = arguments[0];
491 | }
492 |
493 | if (typeof arguments[1] === 'string')
494 | qualifier = arguments[1];
495 |
496 | if (arguments[1] === null)
497 | qualifier = null;
498 |
499 | if (this.orig instanceof Array)
500 | dataArray = this.orig;
501 | else { //object
502 | for (var key in this.orig)
503 | if (this.orig.hasOwnProperty(key))
504 | if (keys)
505 | dataArray.push(key);
506 | else
507 | dataArray.push(this.orig[key]);
508 | }
509 |
510 | var rep = escape + qualifier;
511 | var buildString = [];
512 | for (var i = 0; i < dataArray.length; ++i) {
513 | var shouldQualify = hasVal(qualifier)
514 | if (typeof dataArray[i] == 'number')
515 | shouldQualify &= encloseNumbers;
516 |
517 | if (shouldQualify)
518 | buildString.push(qualifier);
519 |
520 | if (dataArray[i] !== null && dataArray[i] !== undefined) {
521 | var d = new S(dataArray[i]).replaceAll(qualifier, rep).s;
522 | buildString.push(d);
523 | } else
524 | buildString.push('')
525 |
526 | if (shouldQualify)
527 | buildString.push(qualifier);
528 |
529 | if (delim)
530 | buildString.push(delim);
531 | }
532 |
533 | //chop last delim
534 | //console.log(buildString.length)
535 | buildString.length = buildString.length - 1;
536 | return new this.constructor(buildString.join(''));
537 | },
538 |
539 | toString: function() {
540 | return this.s;
541 | },
542 |
543 | //#modified from https://github.com/epeli/underscore.string
544 | underscore: function() {
545 | var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
546 | if ((new S(this.s.charAt(0))).isUpper()) {
547 | s = '_' + s;
548 | }
549 | return new this.constructor(s);
550 | },
551 |
552 | unescapeHTML: function() { //from underscore.string
553 | return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){
554 | var match;
555 |
556 | if (entityCode in escapeChars) {
557 | return escapeChars[entityCode];
558 | } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
559 | return String.fromCharCode(parseInt(match[1], 16));
560 | } else if (match = entityCode.match(/^#(\d+)$/)) {
561 | return String.fromCharCode(~~match[1]);
562 | } else {
563 | return entity;
564 | }
565 | }));
566 | },
567 |
568 | valueOf: function() {
569 | return this.s.valueOf();
570 | },
571 |
572 | //#Added a New Function called wrapHTML.
573 | wrapHTML: function (tagName, tagAttrs) {
574 | var s = this.s, el = (tagName == null) ? 'span' : tagName, elAttr = '', wrapped = '';
575 | if(typeof tagAttrs == 'object') for(var prop in tagAttrs) elAttr += ' ' + prop + '="' +(new this.constructor(tagAttrs[prop])).escapeHTML() + '"';
576 | s = wrapped.concat('<', el, elAttr, '>', this, '', el, '>');
577 | return new this.constructor(s);
578 | }
579 | }
580 |
581 | var methodsAdded = [];
582 | function extendPrototype() {
583 | for (var name in __sp) {
584 | (function(name){
585 | var func = __sp[name];
586 | if (!__nsp.hasOwnProperty(name)) {
587 | methodsAdded.push(name);
588 | __nsp[name] = function() {
589 | String.prototype.s = this;
590 | return func.apply(this, arguments);
591 | }
592 | }
593 | })(name);
594 | }
595 | }
596 |
597 | function restorePrototype() {
598 | for (var i = 0; i < methodsAdded.length; ++i)
599 | delete String.prototype[methodsAdded[i]];
600 | methodsAdded.length = 0;
601 | }
602 |
603 |
604 | /*************************************
605 | /* Attach Native JavaScript String Properties
606 | /*************************************/
607 |
608 | var nativeProperties = getNativeStringProperties();
609 | for (var name in nativeProperties) {
610 | (function(name) {
611 | var stringProp = __nsp[name];
612 | if (typeof stringProp == 'function') {
613 | //console.log(stringProp)
614 | if (!__sp[name]) {
615 | if (nativeProperties[name] === 'string') {
616 | __sp[name] = function() {
617 | //console.log(name)
618 | return new this.constructor(stringProp.apply(this, arguments));
619 | }
620 | } else {
621 | __sp[name] = stringProp;
622 | }
623 | }
624 | }
625 | })(name);
626 | }
627 |
628 |
629 | /*************************************
630 | /* Function Aliases
631 | /*************************************/
632 |
633 | __sp.repeat = __sp.times;
634 | __sp.include = __sp.contains;
635 | __sp.toInteger = __sp.toInt;
636 | __sp.toBool = __sp.toBoolean;
637 | __sp.decodeHTMLEntities = __sp.decodeHtmlEntities //ensure consistent casing scheme of 'HTML'
638 |
639 |
640 | //******************************************************************************
641 | // Set the constructor. Without this, string.js objects are instances of
642 | // Object instead of S.
643 | //******************************************************************************
644 |
645 | __sp.constructor = S;
646 |
647 |
648 | /*************************************
649 | /* Private Functions
650 | /*************************************/
651 |
652 | function getNativeStringProperties() {
653 | var names = getNativeStringPropertyNames();
654 | var retObj = {};
655 |
656 | for (var i = 0; i < names.length; ++i) {
657 | var name = names[i];
658 | var func = __nsp[name];
659 | try {
660 | var type = typeof func.apply('teststring', []);
661 | retObj[name] = type;
662 | } catch (e) {}
663 | }
664 | return retObj;
665 | }
666 |
667 | function getNativeStringPropertyNames() {
668 | var results = [];
669 | if (Object.getOwnPropertyNames) {
670 | results = Object.getOwnPropertyNames(__nsp);
671 | results.splice(results.indexOf('valueOf'), 1);
672 | results.splice(results.indexOf('toString'), 1);
673 | return results;
674 | } else { //meant for legacy cruft, this could probably be made more efficient
675 | var stringNames = {};
676 | var objectNames = [];
677 | for (var name in String.prototype)
678 | stringNames[name] = name;
679 |
680 | for (var name in Object.prototype)
681 | delete stringNames[name];
682 |
683 | //stringNames['toString'] = 'toString'; //this was deleted with the rest of the object names
684 | for (var name in stringNames) {
685 | results.push(name);
686 | }
687 | return results;
688 | }
689 | }
690 |
691 | function Export(str) {
692 | return new S(str);
693 | };
694 |
695 | //attach exports to StringJSWrapper
696 | Export.extendPrototype = extendPrototype;
697 | Export.restorePrototype = restorePrototype;
698 | Export.VERSION = VERSION;
699 | Export.TMPL_OPEN = '{{';
700 | Export.TMPL_CLOSE = '}}';
701 | Export.ENTITIES = ENTITIES;
702 |
703 |
704 |
705 | /*************************************
706 | /* Exports
707 | /*************************************/
708 |
709 | if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
710 | module.exports = Export;
711 |
712 | } else {
713 |
714 | if(typeof define === "function" && define.amd) {
715 | define([], function() {
716 | return Export;
717 | });
718 | } else {
719 | window.S = Export;
720 | }
721 | }
722 |
723 |
724 | /*************************************
725 | /* 3rd Party Private Functions
726 | /*************************************/
727 |
728 | //from sugar.js
729 | function multiArgs(args, fn) {
730 | var result = [], i;
731 | for(i = 0; i < args.length; i++) {
732 | result.push(args[i]);
733 | if(fn) fn.call(args, args[i], i);
734 | }
735 | return result;
736 | }
737 |
738 | //from underscore.string
739 | var escapeChars = {
740 | lt: '<',
741 | gt: '>',
742 | quot: '"',
743 | apos: "'",
744 | amp: '&'
745 | };
746 |
747 | //from underscore.string
748 | var reversedEscapeChars = {};
749 | for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; }
750 |
751 | ENTITIES = {
752 | "amp" : "&",
753 | "gt" : ">",
754 | "lt" : "<",
755 | "quot" : "\"",
756 | "apos" : "'",
757 | "AElig" : 198,
758 | "Aacute" : 193,
759 | "Acirc" : 194,
760 | "Agrave" : 192,
761 | "Aring" : 197,
762 | "Atilde" : 195,
763 | "Auml" : 196,
764 | "Ccedil" : 199,
765 | "ETH" : 208,
766 | "Eacute" : 201,
767 | "Ecirc" : 202,
768 | "Egrave" : 200,
769 | "Euml" : 203,
770 | "Iacute" : 205,
771 | "Icirc" : 206,
772 | "Igrave" : 204,
773 | "Iuml" : 207,
774 | "Ntilde" : 209,
775 | "Oacute" : 211,
776 | "Ocirc" : 212,
777 | "Ograve" : 210,
778 | "Oslash" : 216,
779 | "Otilde" : 213,
780 | "Ouml" : 214,
781 | "THORN" : 222,
782 | "Uacute" : 218,
783 | "Ucirc" : 219,
784 | "Ugrave" : 217,
785 | "Uuml" : 220,
786 | "Yacute" : 221,
787 | "aacute" : 225,
788 | "acirc" : 226,
789 | "aelig" : 230,
790 | "agrave" : 224,
791 | "aring" : 229,
792 | "atilde" : 227,
793 | "auml" : 228,
794 | "ccedil" : 231,
795 | "eacute" : 233,
796 | "ecirc" : 234,
797 | "egrave" : 232,
798 | "eth" : 240,
799 | "euml" : 235,
800 | "iacute" : 237,
801 | "icirc" : 238,
802 | "igrave" : 236,
803 | "iuml" : 239,
804 | "ntilde" : 241,
805 | "oacute" : 243,
806 | "ocirc" : 244,
807 | "ograve" : 242,
808 | "oslash" : 248,
809 | "otilde" : 245,
810 | "ouml" : 246,
811 | "szlig" : 223,
812 | "thorn" : 254,
813 | "uacute" : 250,
814 | "ucirc" : 251,
815 | "ugrave" : 249,
816 | "uuml" : 252,
817 | "yacute" : 253,
818 | "yuml" : 255,
819 | "copy" : 169,
820 | "reg" : 174,
821 | "nbsp" : 160,
822 | "iexcl" : 161,
823 | "cent" : 162,
824 | "pound" : 163,
825 | "curren" : 164,
826 | "yen" : 165,
827 | "brvbar" : 166,
828 | "sect" : 167,
829 | "uml" : 168,
830 | "ordf" : 170,
831 | "laquo" : 171,
832 | "not" : 172,
833 | "shy" : 173,
834 | "macr" : 175,
835 | "deg" : 176,
836 | "plusmn" : 177,
837 | "sup1" : 185,
838 | "sup2" : 178,
839 | "sup3" : 179,
840 | "acute" : 180,
841 | "micro" : 181,
842 | "para" : 182,
843 | "middot" : 183,
844 | "cedil" : 184,
845 | "ordm" : 186,
846 | "raquo" : 187,
847 | "frac14" : 188,
848 | "frac12" : 189,
849 | "frac34" : 190,
850 | "iquest" : 191,
851 | "times" : 215,
852 | "divide" : 247,
853 | "OElig;" : 338,
854 | "oelig;" : 339,
855 | "Scaron;" : 352,
856 | "scaron;" : 353,
857 | "Yuml;" : 376,
858 | "fnof;" : 402,
859 | "circ;" : 710,
860 | "tilde;" : 732,
861 | "Alpha;" : 913,
862 | "Beta;" : 914,
863 | "Gamma;" : 915,
864 | "Delta;" : 916,
865 | "Epsilon;" : 917,
866 | "Zeta;" : 918,
867 | "Eta;" : 919,
868 | "Theta;" : 920,
869 | "Iota;" : 921,
870 | "Kappa;" : 922,
871 | "Lambda;" : 923,
872 | "Mu;" : 924,
873 | "Nu;" : 925,
874 | "Xi;" : 926,
875 | "Omicron;" : 927,
876 | "Pi;" : 928,
877 | "Rho;" : 929,
878 | "Sigma;" : 931,
879 | "Tau;" : 932,
880 | "Upsilon;" : 933,
881 | "Phi;" : 934,
882 | "Chi;" : 935,
883 | "Psi;" : 936,
884 | "Omega;" : 937,
885 | "alpha;" : 945,
886 | "beta;" : 946,
887 | "gamma;" : 947,
888 | "delta;" : 948,
889 | "epsilon;" : 949,
890 | "zeta;" : 950,
891 | "eta;" : 951,
892 | "theta;" : 952,
893 | "iota;" : 953,
894 | "kappa;" : 954,
895 | "lambda;" : 955,
896 | "mu;" : 956,
897 | "nu;" : 957,
898 | "xi;" : 958,
899 | "omicron;" : 959,
900 | "pi;" : 960,
901 | "rho;" : 961,
902 | "sigmaf;" : 962,
903 | "sigma;" : 963,
904 | "tau;" : 964,
905 | "upsilon;" : 965,
906 | "phi;" : 966,
907 | "chi;" : 967,
908 | "psi;" : 968,
909 | "omega;" : 969,
910 | "thetasym;" : 977,
911 | "upsih;" : 978,
912 | "piv;" : 982,
913 | "ensp;" : 8194,
914 | "emsp;" : 8195,
915 | "thinsp;" : 8201,
916 | "zwnj;" : 8204,
917 | "zwj;" : 8205,
918 | "lrm;" : 8206,
919 | "rlm;" : 8207,
920 | "ndash;" : 8211,
921 | "mdash;" : 8212,
922 | "lsquo;" : 8216,
923 | "rsquo;" : 8217,
924 | "sbquo;" : 8218,
925 | "ldquo;" : 8220,
926 | "rdquo;" : 8221,
927 | "bdquo;" : 8222,
928 | "dagger;" : 8224,
929 | "Dagger;" : 8225,
930 | "bull;" : 8226,
931 | "hellip;" : 8230,
932 | "permil;" : 8240,
933 | "prime;" : 8242,
934 | "Prime;" : 8243,
935 | "lsaquo;" : 8249,
936 | "rsaquo;" : 8250,
937 | "oline;" : 8254,
938 | "frasl;" : 8260,
939 | "euro;" : 8364,
940 | "image;" : 8465,
941 | "weierp;" : 8472,
942 | "real;" : 8476,
943 | "trade;" : 8482,
944 | "alefsym;" : 8501,
945 | "larr;" : 8592,
946 | "uarr;" : 8593,
947 | "rarr;" : 8594,
948 | "darr;" : 8595,
949 | "harr;" : 8596,
950 | "crarr;" : 8629,
951 | "lArr;" : 8656,
952 | "uArr;" : 8657,
953 | "rArr;" : 8658,
954 | "dArr;" : 8659,
955 | "hArr;" : 8660,
956 | "forall;" : 8704,
957 | "part;" : 8706,
958 | "exist;" : 8707,
959 | "empty;" : 8709,
960 | "nabla;" : 8711,
961 | "isin;" : 8712,
962 | "notin;" : 8713,
963 | "ni;" : 8715,
964 | "prod;" : 8719,
965 | "sum;" : 8721,
966 | "minus;" : 8722,
967 | "lowast;" : 8727,
968 | "radic;" : 8730,
969 | "prop;" : 8733,
970 | "infin;" : 8734,
971 | "ang;" : 8736,
972 | "and;" : 8743,
973 | "or;" : 8744,
974 | "cap;" : 8745,
975 | "cup;" : 8746,
976 | "int;" : 8747,
977 | "there4;" : 8756,
978 | "sim;" : 8764,
979 | "cong;" : 8773,
980 | "asymp;" : 8776,
981 | "ne;" : 8800,
982 | "equiv;" : 8801,
983 | "le;" : 8804,
984 | "ge;" : 8805,
985 | "sub;" : 8834,
986 | "sup;" : 8835,
987 | "nsub;" : 8836,
988 | "sube;" : 8838,
989 | "supe;" : 8839,
990 | "oplus;" : 8853,
991 | "otimes;" : 8855,
992 | "perp;" : 8869,
993 | "sdot;" : 8901,
994 | "lceil;" : 8968,
995 | "rceil;" : 8969,
996 | "lfloor;" : 8970,
997 | "rfloor;" : 8971,
998 | "lang;" : 9001,
999 | "rang;" : 9002,
1000 | "loz;" : 9674,
1001 | "spades;" : 9824,
1002 | "clubs;" : 9827,
1003 | "hearts;" : 9829,
1004 | "diams;" : 9830
1005 | }
1006 |
1007 |
1008 | }).call(this);
1009 |
--------------------------------------------------------------------------------