?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,function(a,d,e,f,g){return d=d.toLowerCase(),b[d]=G(e),f?f+g:(g&&(c[d]=g.replace(/"/g,""")),"")}),a=a.replace(/~0/,""),a},m=function(a){a=a.replace(/\n/g,"\n\n");var b="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside",c="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside";return a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,n),a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,n),a=a.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,n),a=a.replace(/(\n\n[ ]{0,3}[ \t]*(?=\n{2,}))/g,n),a=a.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,n),a=a.replace(/\n\n/g,"\n"),a},n=function(a,b){var c=b;return c=c.replace(/\n\n/g,"\n"),c=c.replace(/^\n/,""),c=c.replace(/\n+$/g,""),c="\n\n~K"+(d.push(c)-1)+"K\n\n",c},o=function(a){a=v(a);var b=A(" ");return a=a.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,b),a=x(a),a=y(a),a=E(a),a=m(a),a=F(a),a},p=function(a){return a=B(a),a=q(a),a=H(a),a=t(a),a=r(a),a=I(a),a=G(a),a=D(a),a=a.replace(/ +\n/g," \n"),a},q=function(a){var b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi;return a=a.replace(b,function(a){var b=a.replace(/(.)<\/?code>(?=.)/g,"$1`");return b=N(b,"\\`*_"),b}),a},r=function(a){return a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,s),a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,s),a=a.replace(/(\[([^\[\]]+)\])()()()()()/g,s),a},s=function(a,d,e,f,g,h,i,j){j==undefined&&(j="");var k=d,l=e,m=f.toLowerCase(),n=g,o=j;if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(b[m]!=undefined)n=b[m],c[m]!=undefined&&(o=c[m]);else{if(!(k.search(/\(\s*\)$/m)>-1))return k;n=""}}n=N(n,"*_");var p='"+l+" ",p},t=function(a){return a=a.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,u),a=a.replace(/(!\[(.*?)\]\s?\([ \t]*()(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,u),a},u=function(a,d,e,f,g,h,i,j){var k=d,l=e,m=f.toLowerCase(),n=g,o=j;o||(o="");if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(b[m]==undefined)return k;n=b[m],c[m]!=undefined&&(o=c[m])}l=l.replace(/"/g,"""),n=N(n,"*_");var p=' ",p},v=function(a){function b(a){return a.replace(/[^\w]/g,"").toLowerCase()}return a=a.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(a,c){return A(''+p(c)+" ")}),a=a.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(a,c){return A(''+p(c)+" ")}),a=a.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(a,c,d){var e=c.length;return A("'+p(d)+" ")}),a},w,x=function(a){a+="~0";var b=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;return e?a=a.replace(b,function(a,b,c){var d=b,e=c.search(/[*+-]/g)>-1?"ul":"ol";d=d.replace(/\n{2,}/g,"\n\n\n");var f=w(d);return f=f.replace(/\s+$/,""),f="<"+e+">"+f+""+e+">\n",f}):(b=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g,a=a.replace(b,function(a,b,c,d){var e=b,f=c,g=d.search(/[*+-]/g)>-1?"ul":"ol",f=f.replace(/\n{2,}/g,"\n\n\n"),h=w(f);return h=e+"<"+g+">\n"+h+""+g+">\n",h})),a=a.replace(/~0/,""),a};w=function(a){return e++,a=a.replace(/\n{2,}$/,"\n"),a+="~0",a=a.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(a,b,c,d,e){var f=e,g=b,h=c;return g||f.search(/\n{2,}/)>-1?f=o(L(f)):(f=x(L(f)),f=f.replace(/\n$/,""),f=p(f)),""+f+" \n"}),a=a.replace(/~0/g,""),e--,a};var y=function(a){return a+="~0",a=a.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(a,b,c){var d=b,e=c;return d=C(L(d)),d=M(d),d=d.replace(/^\n+/g,""),d=d.replace(/\n+$/g,""),d=""+d+"\n
",A(d)+e}),a=a.replace(/~0/,""),a},z=function(a){return a+="~0",a=a.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,function(a,b,c){var d=b,e=c;return e=C(e),e=M(e),e=e.replace(/^\n+/g,""),e=e.replace(/\n+$/g,""),e=""+e+"\n
",A(e)}),a=a.replace(/~0/,""),a},A=function(a){return a=a.replace(/(^\n+|\n+$)/g,""),"\n\n~K"+(d.push(a)-1)+"K\n\n"},B=function(a){return a=a.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(a,b,c,d,e){var f=d;return f=f.replace(/^([ \t]*)/g,""),f=f.replace(/[ \t]*$/g,""),f=C(f),b+""+f+"
"}),a},C=function(a){return a=a.replace(/&/g,"&"),a=a.replace(//g,">"),a=N(a,"*_{}[]\\",!1),a},D=function(a){return a=a.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"$2 "),a=a.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"$2 "),a},E=function(a){return a=a.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(a,b){var c=b;return c=c.replace(/^[ \t]*>[ \t]?/gm,"~0"),c=c.replace(/~0/g,""),c=c.replace(/^[ \t]+$/gm,""),c=o(c),c=c.replace(/(^|\n)/g,"$1 "),c=c.replace(/(\s*[^\r]+?<\/pre>)/gm,function(a,b){var c=b;return c=c.replace(/^ /mg,"~0"),c=c.replace(/~0/g,""),c}),A("\n"+c+"\n ")}),a},F=function(a){a=a.replace(/^\n+/g,""),a=a.replace(/\n+$/g,"");var b=a.split(/\n{2,}/g),c=[],e=b.length;for(var f=0;f=0?c.push(g):g.search(/\S/)>=0&&(g=p(g),g=g.replace(/^([ \t]*)/g,""),g+="
",c.push(g))}e=c.length;for(var f=0;f=0){var h=d[RegExp.$1];h=h.replace(/\$/g,"$$$$"),c[f]=c[f].replace(/~K\d+K/,h)}return c.join("\n\n")},G=function(a){return a=a.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"),a=a.replace(/<(?![a-z\/?\$!])/gi,"<"),a},H=function(a){return a=a.replace(/\\(\\)/g,O),a=a.replace(/\\([`*_{}\[\]()>#+-.!])/g,O),a},I=function(a){return a=a.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'$1 '),a=a.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(a,b){return J(K(b))}),a},J=function(a){var b=[function(a){return""+a.charCodeAt(0)+";"},function(a){return""+a.charCodeAt(0).toString(16)+";"},function(a){return a}];return a="mailto:"+a,a=a.replace(/./g,function(a){if(a=="@")a=b[Math.floor(Math.random()*2)](a);else if(a!=":"){var c=Math.random();a=c>.9?b[2](a):c>.45?b[1](a):b[0](a)}return a}),a=''+a+" ",a=a.replace(/">.+:/g,'">'),a},K=function(a){return a=a.replace(/~E(\d+)E/g,function(a,b){var c=parseInt(b);return String.fromCharCode(c)}),a},L=function(a){return a=a.replace(/^(\t|[ ]{1,4})/gm,"~0"),a=a.replace(/~0/g,""),a},M=function(a){return a=a.replace(/\t(?=\t)/g," "),a=a.replace(/\t/g,"~A~B"),a=a.replace(/~B(.+?)~A/g,function(a,b,c){var d=b,e=4-d.length%4;for(var f=0;f li > a,
52 | .navbar-short .navbar-nav > li > a {
53 | -webkit-transition: all 0.2s linear;
54 | transition: all 0.2s linear;
55 | }
56 |
57 | .navbar-short {
58 | min-height: 40px;
59 | }
60 | .navbar-short .navbar-brand {
61 | font-size: 16px;
62 | padding: 13px 15px 10px;
63 | }
64 | .navbar-short .navbar-nav > li > a {
65 | padding-top: 12px;
66 | padding-bottom: 12px;
67 | }
68 |
69 |
70 | .navbar-tall {
71 | min-height: 70px;
72 | }
73 | .navbar-tall .navbar-brand {
74 | font-size: 24px;
75 | padding: 25px 15px;
76 | }
77 | .navbar-tall .navbar-nav > li > a {
78 | padding-top: 25px;
79 | }
80 |
81 |
82 |
83 | /**
84 | * Docs Buttons
85 | */
86 |
87 | /* Demo buttons are all tags, so
88 | * lets style these directly.
89 | */
90 | button {
91 | float: right !important;
92 | }
93 |
94 |
95 | /* Fixed button, bottom right */
96 | .btn-fixed-bottom {
97 | position: fixed;
98 | bottom: 10px;
99 | right: 20px;
100 | display: none;
101 | }
102 |
103 |
104 | /* Toggles navbar classes */
105 | .btn-hide-show {
106 | margin-right: 10px;
107 | }
108 |
109 |
110 | /* Light theme */
111 | .btn-light {
112 | color: #555;
113 | background-color: rgba(0, 0, 0,.1);
114 | }
115 | .btn-light:hover {
116 | color: #111;
117 | background-color: rgba(0, 0, 0,.25);
118 | }
119 |
120 | /* Dark theme */
121 | .btn-dark {
122 | color: #fff;
123 | background-color: rgba(0, 0, 0,.5);
124 | }
125 | .btn-dark:hover {
126 | color: #fff;
127 | background-color: rgba(0, 0, 0,.9);
128 | }
129 |
130 |
131 |
132 | /* Buttons displayed throughout the content */
133 | .btn-showup {
134 | position: relative;
135 | color: #fff;
136 | font-weight: normal;
137 | background-color: #463265;
138 | border-color: #3F2961;
139 | }
140 | .btn:focus,
141 | .btn-showup:hover,
142 | .btn-showup:focus {
143 | color: #fff;
144 | outline: none;
145 | background-color: #39235A;
146 | border-color: #39235A;
147 | }
148 |
149 |
--------------------------------------------------------------------------------
/web/showup.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Showup.js jQuery Plugin
3 | * http://github.com/jonschlinkert/showup
4 | *
5 | * Copyright (c) 2013 Jon Schlinkert, contributors
6 | * Licensed under the MIT License (MIT).
7 | */
8 |
9 |
10 | (function( $ ) {
11 | $.fn.showUp = function(ele, options) {
12 | options = options || {};
13 |
14 | var target = $(ele);
15 | var down = options.down || 'navbar-hide';
16 | var up = options.up || 'navbar-show';
17 | var btnHideShow = options.btnHideShow || '.btn-hide-show';
18 | var hideOffset = options.offset || 110;
19 | var previousScroll = 0;
20 |
21 | $(window).scroll(function () {
22 | // var currentScroll = $(this).scrollTop();
23 | if ($(this).scrollTop() > hideOffset) {
24 | if ($(this).scrollTop() > previousScroll) {
25 | // Action on scroll down
26 | target.removeClass(up).addClass(down);
27 | } else {
28 | // Action on scroll up
29 | target.removeClass(down).addClass(up);
30 | }
31 | }
32 | previousScroll = $(this).scrollTop();
33 | });
34 |
35 | // Toggle visibility of target on click
36 | $(btnHideShow).click(function () {
37 | if (target.hasClass(down)) {
38 | target.removeClass(down).addClass(up);
39 | } else {
40 | target.removeClass(up).addClass(down);
41 | }
42 | });
43 | };
44 | })( jQuery );
45 |
46 | // TODO: make customizable
47 | $(document).ready(function () {
48 | var duration = 420;
49 | var showOffset = 220;
50 | var btnFixed = '.btn-fixed-bottom';
51 | var btnToTopClass = '.back-to-top';
52 |
53 | $(window).scroll(function () {
54 | if ($(this).scrollTop() > showOffset) {
55 | $(btnFixed).fadeIn(duration);
56 | } else {
57 | $(btnFixed).fadeOut(duration);
58 | }
59 | });
60 |
61 | $(btnToTopClass).click(function (event) {
62 | event.preventDefault();
63 | $('html, body').animate({
64 | scrollTop: 0
65 | }, duration);
66 | return false;
67 | });
68 | });
69 |
70 |
--------------------------------------------------------------------------------
/web/style.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 62.5%;
3 | color: #000;
4 | background-color: #fff;
5 | }
6 | #dokuwiki__site {
7 | font-size: 160%;
8 | }
9 | body.microalg {
10 | font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
11 | line-height: 1.6;
12 | font-weight: 400;
13 | font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
14 | max-width: 800px;
15 | width: 95%;
16 | margin: 0px auto;
17 | }
18 | .microalg ul {
19 | list-style: outside;
20 | }
21 | .microalg p, li {
22 | line-height: 1.3em;
23 | }
24 | .microalg a:link {color:#337;}
25 | .microalg a:visited {color:#333;}
26 | .microalg a:hover {color:#000;}
27 | .microalg a:active {color:#000;}
28 | .microalg h1 a,
29 | .microalg h2 a,
30 | .microalg h3 a,
31 | .microalg h4 a,
32 | .microalg h5 a,
33 | .microalg h6 a {
34 | text-decoration: none;
35 | border: 0 none;
36 | }
37 | .microalg h2 {
38 | margin-top: 3.2em;
39 | }
40 | .microalg h3 {
41 | margin-top: 2em;
42 | }
43 | .microalg.doc h2 {
44 | border-top: 1px solid black;
45 | padding-top: 0.5em;
46 | }
47 | .microalg code {
48 | font-size: 1.2em;
49 | margin: 0 2px;
50 | padding: 0px 5px;
51 | border: 1px solid #AAA;
52 | background-color: #EEE;
53 | border-radius: 3px;
54 | white-space: nowrap;
55 | }
56 | .microalg pre code {
57 | display: block;
58 | white-space: pre;
59 | position: relative;
60 | }
61 | .microalg blockquote {
62 | background-color: #F9F9F9;
63 | border: solid #CCC 1px;
64 | border-left: solid #DDD 5px;
65 | padding-left: 0.7em;
66 | padding-top: 1px;
67 | padding-bottom: 1px;
68 | }
69 | .malg-container {
70 | width: 95%;
71 | margin: 0px auto;
72 | }
73 | .malg-export {
74 | line-height: 1.2em;
75 | font-family: monospace;
76 | white-space: pre;
77 | border: solid 1px;
78 | padding: 3px;
79 | margin-bottom: 1em;
80 | }
81 | .malg-export-eval {
82 | text-align: right;
83 | }
84 | .malg-export-eval input {
85 | background-color: #eee;
86 | margin: 1em 0 1em 1em;
87 | border: none;
88 | }
89 | .malg-guide {
90 | color: #ddd;
91 | }
92 | .malg-blockly-iframe {
93 | height: 350px;
94 | width: 100%;
95 | border-style: solid;
96 | border-width: 1px;
97 | border-color: #aaa;
98 | }
99 | .malg-editor, .malg-repl {
100 | width: 100%;
101 | }
102 | .malg-ok-editor, .malg-ok {
103 | font-family: 'Courier New', Courier, monospace;
104 | line-height: 1.5;
105 | margin: 2px;
106 | background-color: #ddd;
107 | border: 1px solid #BABABA;
108 | }
109 | .malg-ok {
110 | width: 100%;
111 | }
112 | .malg-ok-editor {
113 | width: 75%;
114 | }
115 | .malg-output-type {
116 | float: right;
117 | margin: 2px;
118 | width: 20%;
119 | }
120 | .malg-error {
121 | color: red;
122 | }
123 | .malg-freq-error {
124 | color: black;
125 | }
126 | .malg-display {
127 | font-family: "Courier New",Courier,monospace;
128 | margin-bottom: 2em;
129 | border-color: black;
130 | border-style: solid;
131 | border-width: 1px;
132 | -webkit-border-radius: 5px;
133 | -moz-border-radius: 5px;
134 | border-radius: 5px;
135 | background-color: white;
136 | min-height: 1em;
137 | padding: 2px;
138 | }
139 | pre.brut {
140 | font-size: 1.3em;
141 | line-height: 1em;
142 | margin: 0px;
143 | }
144 | .malg-sketch {
145 | border: solid 1px;
146 | margin-bottom: 3em;
147 | }
148 | .microalg .terminal, .microalg .cmd {
149 | width: 93%;
150 | margin: 0px auto;
151 | color: black;
152 | background-color: white;
153 | font-family: 'Courier New', Courier, monospace;
154 | }
155 | .microalg .terminal {
156 | border: solid 1px #BABABA;
157 | }
158 | .microalg .link-right {
159 | text-align: right;
160 | }
161 | .microalg .link-snippet {
162 | text-align: right;
163 | }
164 | .microalg .link-snippet a {
165 | text-decoration: none;
166 | border-bottom: 0;
167 | background-color: #eee;
168 | padding: 0 .5em 0 .5em;
169 | }
170 | .microalg .link-snippet a:hover {
171 | background-color: #ddd;
172 | }
173 | a.wp:after, a.offi:after, a.email:after {
174 | color: black;
175 | text-decoration: none;
176 | display: inline-block;
177 | vertical-align: super;
178 | font-size: 50%;
179 | }
180 | a.wp:after {
181 | content:"(wp)";
182 | }
183 | a.offi:after {
184 | content:"(officiel)";
185 | }
186 | a.email:after {
187 | content:"(email)";
188 | }
189 | .microalg a {
190 | text-decoration: none;
191 | padding-bottom: 1px;
192 | border-bottom: 1px solid;
193 | }
194 | #bla {
195 | width: 60%;
196 | margin: 0px auto;
197 | }
198 | #bla h1 {
199 | text-align: center;
200 | }
201 | .microalg .navbar {
202 | position: fixed;
203 | top: 0;
204 | right: 0;
205 | margin: 1em;
206 | padding: 1em;
207 | z-index: 120;
208 | background-color: #eee;
209 | }
210 | .microalg dt {
211 | padding-top: 2em;
212 | }
213 | .microalg dt span {
214 | font-family: 'Courier New', Courier, monospace;
215 | border: 1px solid black;
216 | padding: 0.3em 0.5em 1px 0.7em;
217 | -webkit-border-top-left-radius: 1em;
218 | -moz-border-top-left-radius: 1em;
219 | border-top-left-radius: 1em;
220 | }
221 | .microalg dt span a {
222 | color: black !important;
223 | }
224 |
--------------------------------------------------------------------------------
/web/tabIndent.js:
--------------------------------------------------------------------------------
1 | tabIndent = {
2 | version: '0.1.8',
3 | config: {
4 | tab: '\t'
5 | },
6 | events: {
7 | keydown: function(e) {
8 | var tab = tabIndent.config.tab;
9 | var tabWidth = tab.length;
10 | if (e.keyCode === 9) {
11 | e.preventDefault();
12 | var currentStart = this.selectionStart,
13 | currentEnd = this.selectionEnd;
14 | if (e.shiftKey === false) {
15 | // Normal Tab Behaviour
16 | if (!tabIndent.isMultiLine(this)) {
17 | // Add tab before selection, maintain highlighted text selection
18 | this.value = this.value.slice(0, currentStart) + tab + this.value.slice(currentStart);
19 | this.selectionStart = currentStart + tabWidth;
20 | this.selectionEnd = currentEnd + tabWidth;
21 | } else {
22 | // Iterating through the startIndices, if the index falls within selectionStart and selectionEnd, indent it there.
23 | var startIndices = tabIndent.findStartIndices(this),
24 | l = startIndices.length,
25 | newStart = undefined,
26 | newEnd = undefined,
27 | affectedRows = 0;
28 |
29 | while(l--) {
30 | var lowerBound = startIndices[l];
31 | if (startIndices[l+1] && currentStart != startIndices[l+1]) lowerBound = startIndices[l+1];
32 |
33 | if (lowerBound >= currentStart && startIndices[l] < currentEnd) {
34 | this.value = this.value.slice(0, startIndices[l]) + tab + this.value.slice(startIndices[l]);
35 |
36 | newStart = startIndices[l];
37 | if (!newEnd) newEnd = (startIndices[l+1] ? startIndices[l+1] - 1 : 'end');
38 | affectedRows++;
39 | }
40 | }
41 |
42 | this.selectionStart = newStart;
43 | this.selectionEnd = (newEnd !== 'end' ? newEnd + (tabWidth * affectedRows) : this.value.length);
44 | }
45 | } else {
46 | // Shift-Tab Behaviour
47 | if (!tabIndent.isMultiLine(this)) {
48 | if (this.value.substr(currentStart - tabWidth, tabWidth) == tab) {
49 | // If there's a tab before the selectionStart, remove it
50 | this.value = this.value.substr(0, currentStart - tabWidth) + this.value.substr(currentStart);
51 | this.selectionStart = currentStart - tabWidth;
52 | this.selectionEnd = currentEnd - tabWidth;
53 | } else if (this.value.substr(currentStart - 1, 1) == "\n" && this.value.substr(currentStart, tabWidth) == tab) {
54 | // However, if the selection is at the start of the line, and the first character is a tab, remove it
55 | this.value = this.value.substring(0, currentStart) + this.value.substr(currentStart + tabWidth);
56 | this.selectionStart = currentStart;
57 | this.selectionEnd = currentEnd - tabWidth;
58 | }
59 | } else {
60 | // Iterating through the startIndices, if the index falls within selectionStart and selectionEnd, remove an indent from that row
61 | var startIndices = tabIndent.findStartIndices(this),
62 | l = startIndices.length,
63 | newStart = undefined,
64 | newEnd = undefined,
65 | affectedRows = 0;
66 |
67 | while(l--) {
68 | var lowerBound = startIndices[l];
69 | if (startIndices[l+1] && currentStart != startIndices[l+1]) lowerBound = startIndices[l+1];
70 |
71 | if (lowerBound >= currentStart && startIndices[l] < currentEnd) {
72 | if (this.value.substr(startIndices[l], tabWidth) == tab) {
73 | // Remove a tab
74 | this.value = this.value.slice(0, startIndices[l]) + this.value.slice(startIndices[l] + tabWidth);
75 | affectedRows++;
76 | } else {} // Do nothing
77 |
78 | newStart = startIndices[l];
79 | if (!newEnd) newEnd = (startIndices[l+1] ? startIndices[l+1] - 1 : 'end');
80 | }
81 | }
82 |
83 | this.selectionStart = newStart;
84 | this.selectionEnd = (newEnd !== 'end' ? newEnd - (affectedRows * tabWidth) : this.value.length);
85 | }
86 | }
87 | } else if (e.keyCode === 27) { // Esc
88 | tabIndent.events.disable(e);
89 | } else if (e.keyCode === 13 && e.shiftKey === false) { // Enter
90 | var self = tabIndent,
91 | cursorPos = this.selectionStart,
92 | startIndices = self.findStartIndices(this),
93 | numStartIndices = startIndices.length,
94 | startIndex = 0,
95 | endIndex = 0,
96 | tabMatch = new RegExp("^" + tab.replace('\t', '\\t').replace(/ /g, '\\s') + "+", 'g'),
97 | lineText = '';
98 | tabs = null;
99 |
100 | for(var x=0;x= startIndices[x]) && (cursorPos < startIndices[x+1])) {
102 | startIndex = startIndices[x];
103 | endIndex = startIndices[x+1] - 1;
104 | break;
105 | } else {
106 | startIndex = startIndices[numStartIndices-1];
107 | endIndex = this.value.length;
108 | }
109 | }
110 |
111 | lineText = this.value.slice(startIndex, endIndex);
112 | tabs = lineText.match(tabMatch);
113 | if (tabs !== null) {
114 | e.preventDefault();
115 | var indentText = tabs[0];
116 | var indentWidth = indentText.length;
117 | var inLinePos = cursorPos - startIndex;
118 | if (indentWidth > inLinePos) {
119 | indentWidth = inLinePos;
120 | indentText = indentText.slice(0, inLinePos);
121 | }
122 |
123 | this.value = this.value.slice(0, cursorPos) + "\n" + indentText + this.value.slice(cursorPos);
124 | this.selectionStart = cursorPos + indentWidth + 1;
125 | this.selectionEnd = this.selectionStart;
126 | }
127 | }
128 | },
129 | disable: function(e) {
130 | var events = this;
131 |
132 | // Temporarily suspend the main tabIndent event
133 | tabIndent.remove(e.target);
134 | },
135 | focus: function() {
136 | var self = tabIndent,
137 | el = this,
138 | delayedRefocus = setTimeout(function() {
139 | var classes = (el.getAttribute('class') || '').split(' '),
140 | contains = classes.indexOf('tabIndent');
141 |
142 | el.addEventListener('keydown', self.events.keydown);
143 | el.style.backgroundImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAAAEgAAABIAEbJaz4AAAKZSURBVEjH7ZRfSFNRHMe/9+/+3G26tUn+ycywgURgUBAUJlIhWlEQEjN8yQcfolKJxJAefOjRCnT0IPYQ9iRa9FAYJiaUVP4twf7gzJzpnDbdzHt3z+3Fua3dO4Ne/f5ezjmc8+F7zvmeA2zrv0VFGlexAssFw1mG1pqqUL8npGY60Bw3ykYaOVjlrFXmEyw0AQj6g53UONQBO8DBzuiT2tUx+gR/mwACBQpIUoACBZoAZaOSiWwFIFs4oMMS9/boZVF8T8vtkbEofatiRKF9mXK6M7tTyyxRaPwWtJezIu9+9cNzxHk/n9938rz6IWpvgRdZd5/HcsvC9jadqk6Z0qkBiCaAF3UtX8cy6h1mwlnLhsuZuRvqABlyNJqb0q0ZWsb7uUVHlXAahWl1y3M2tVuQVR1Q0Pl0dwZ67KbZtGnX/ma++/FsCCY1ANlAxIuT2NZP3XB/GRKc9qKhKTYnd4auJbIqINEBDa5zoWWByoS1jocR+loKpKGJKqBLybN/OQN2Tmodv4jCtYIMYurnP5sLf+V5XK4DbFv4haaDCEABA/J88GdegD1I2+heY0Xj7M1itiMjP8srzutjXMbkIDZKCrAcfGOt8LwODimYnzzjLcHIx5VFwPekZrhVPYmxyVNAvZP8KV28SykClo6XF4/t9LpC2TTIteulJepJjD5nCjL8E56sMHt40NYYqE51ZnZIfmGXYBC68p/6v6UkApSI8Y2ejPVKhyE0PdLDPcg+Z003G0W7YUmmvo/WtjXgbiKAAQNGpjYRDOwWILx3dV16ZBsx3QsdYi4JNUw6uCvMbrUcWFAvPWznfH9/GQHR5xAbPuTumRFWvS+ZwDGyJFfidkxWk2oaIfTRk8RI0YqMAQBAL7YVrz/iUDx4QII4/QAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxMi0xMi0wMVQwMDowNjo0My0wNTowMLKpTWYAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTItMTItMDFUMDA6MDY6NDMtMDU6MDDD9PXaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAABJRU5ErkJggg==)";
144 | el.style.backgroundPosition = 'top right';
145 | el.style.backgroundRepeat = 'no-repeat';
146 |
147 | if (contains !== -1) classes.splice(contains, 1);
148 | classes.push('tabIndent-rendered');
149 | el.setAttribute('class', classes.join(' '));
150 |
151 | el.removeEventListener('focus', self.events.keydown);
152 | }, 500);
153 |
154 | // If they were just tabbing through the input, let them continue unimpeded
155 | el.addEventListener('blur', function b() {
156 | clearTimeout(delayedRefocus);
157 | el.removeEventListener('blur', b);
158 | });
159 | }
160 | },
161 | render: function(el) {
162 | var self = this;
163 |
164 | if (el.nodeName === 'TEXTAREA') {
165 | el.addEventListener('focus', self.events.focus);
166 |
167 | el.addEventListener('blur', function b(e) {
168 | self.events.disable(e);
169 | });
170 | }
171 | },
172 | renderAll: function() {
173 | // Find all elements with the tabIndent class
174 | var textareas = document.getElementsByTagName('textarea'),
175 | t = textareas.length,
176 | contains = -1,
177 | classes = [],
178 | el = undefined;
179 |
180 | while(t--) {
181 | classes = (textareas[t].getAttribute('class') || '').split(' ');
182 | contains = classes.indexOf('tabIndent');
183 |
184 | if (contains !== -1) {
185 | el = textareas[t];
186 | this.render(el);
187 | }
188 | contains = -1;
189 | classes = [];
190 | el = undefined;
191 | }
192 | },
193 | remove: function(el) {
194 | if (el.nodeName === 'TEXTAREA') {
195 | var classes = (el.getAttribute('class') || '').split(' '),
196 | contains = classes.indexOf('tabIndent-rendered');
197 |
198 | if (contains !== -1) {
199 | el.removeEventListener('keydown', this.events.keydown);
200 | el.style.backgroundImage = '';
201 |
202 | classes.splice(contains, 1);
203 | classes.push('tabIndent');
204 | el.setAttribute('class', (classes.length > 1 ? classes.join(' ') : classes[0]));
205 | }
206 | }
207 | },
208 | removeAll: function() {
209 | // Find all elements with the tabIndent class
210 | var textareas = document.getElementsByTagName('textarea'),
211 | t = textareas.length,
212 | contains = -1,
213 | classes = [],
214 | el = undefined;
215 |
216 | while(t--) {
217 | classes = (textareas[t].getAttribute('class') || '').split(' ');
218 | contains = classes.indexOf('tabIndent-rendered');
219 |
220 | if (contains !== -1) {
221 | el = textareas[t];
222 | this.remove(el);
223 | }
224 | contains = -1;
225 | classes = [];
226 | el = undefined;
227 | }
228 | },
229 | isMultiLine: function(el) {
230 | // Extract the selection
231 | var snippet = el.value.slice(el.selectionStart, el.selectionEnd),
232 | nlRegex = new RegExp(/\n/);
233 |
234 | if (nlRegex.test(snippet)) return true;
235 | else return false;
236 | },
237 | findStartIndices: function(el) {
238 | var text = el.value,
239 | startIndices = [],
240 | offset = 0;
241 |
242 | while(text.match(/\n/) && text.match(/\n/).length > 0) {
243 | offset = (startIndices.length > 0 ? startIndices[startIndices.length - 1] : 0);
244 | var lineEnd = text.search("\n");
245 | startIndices.push(lineEnd + offset + 1);
246 | text = text.substring(lineEnd + 1);
247 | }
248 | startIndices.unshift(0);
249 |
250 | return startIndices;
251 | }
252 | }
253 |
--------------------------------------------------------------------------------