├── README.txt ├── code.html ├── css ├── bck.png ├── bckk.png ├── bootstrap.css ├── hstyle.css ├── jquery-linedtextarea.css ├── style.css ├── tooltipster-light.css └── tooltipster.css ├── examples.html ├── fonts ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.svg ├── glyphicons-halflings-regular.ttf └── glyphicons-halflings-regular.woff ├── images ├── Picture1.png ├── acche.png ├── ayoton.png ├── baad.png ├── cholbe.png ├── contact.png ├── dekhao.png ├── favicon - Copy.png ├── favicon.png ├── function.png ├── home.png ├── hometext.png ├── jodi.png ├── loader.png ├── logo2.png ├── nahole.png ├── nao.png ├── rakho.png ├── set.png ├── shorao.png ├── shorto.png ├── songkha.png ├── thamo.png └── uttor.png ├── index.html ├── indextest.html ├── jquery-linedtextarea.html ├── js ├── base64.js ├── bootstrap.js ├── formState.js ├── jScritp.js ├── jquery-linedtextarea.js ├── jquery.a-tools-1.4.1.js ├── jquery.asuggest.js ├── jquery.js ├── jquery.sticky.js ├── jquery.tooltipster.js ├── print.js ├── text.js └── toktrans.js ├── test.html └── tutorial.html /README.txt: -------------------------------------------------------------------------------- 1 | ChaScript was designed as a learning platform for leaning computer programming in Bengali. It can be a stepping stone for people to learn how to code but thinks language can be a barrier for them to learn something. 2 | 3 | It is build with ECMA Script grammar and is parsed using JISON JavaScript parser. 4 | 5 | Visit: http://sjishan.github.io/chascript/ 6 | -------------------------------------------------------------------------------- /code.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | চা Script - Coding Environment 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 44 | 45 | 46 | 47 |
48 |
49 | 57 | 58 | 59 |
60 | 61 | 62 |
63 | 72 |
73 | 74 | 75 |
76 | 77 |
78 |
79 | 92 |
93 |
94 | 95 |
96 | 97 |
98 | 108 |
109 | 154 |
155 | 156 |
157 | 158 |
159 | 165 |
166 | 167 | 168 |
169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 |
179 | Loading... 180 |
181 | 182 | 183 | -------------------------------------------------------------------------------- /css/bck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/css/bck.png -------------------------------------------------------------------------------- /css/bckk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/css/bckk.png -------------------------------------------------------------------------------- /css/hstyle.css: -------------------------------------------------------------------------------- 1 | html 2 | { 3 | text-align: center; 4 | } 5 | 6 | body 7 | { 8 | background: url('bckk.png'); 9 | background-position:right top; 10 | background-attachment:fixed; 11 | background-repeat:no-repeat; 12 | background-color: #c3b68a; 13 | width:100%; 14 | min-height: 100%; 15 | display: inline-block; 16 | margin: 0px auto; 17 | text-align: center; 18 | } 19 | 20 | 21 | a 22 | { 23 | text-decoration: none !important; 24 | } 25 | 26 | .container-non-responsive { 27 | 28 | /* Set width to your desired site width */ 29 | width: 1343px; 30 | display: inline-block; 31 | margin: 0px auto; 32 | text-align: center; 33 | } 34 | .logo 35 | { 36 | margin-left: 25px; 37 | } 38 | .head 39 | { 40 | z-index: 99999; 41 | } 42 | #cnav 43 | { 44 | height: 45px; 45 | text-align: left; 46 | background-color: #8c7468; 47 | width:1343px; 48 | -webkit-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 49 | -moz-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 50 | box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 51 | } 52 | 53 | #cnav ul 54 | { 55 | margin:0; 56 | list-style: none; 57 | height:45px; 58 | } 59 | 60 | #cnav ul li 61 | { 62 | display:inline-table; 63 | } 64 | 65 | 66 | #cnav > ul > li > a 67 | { 68 | margin:0; 69 | height:40px; 70 | line-height: 40px; 71 | font-size: 97%; 72 | display:inline-table; 73 | padding: 0px 12px; 74 | padding-top: 5px; 75 | color:#ffffff; 76 | 77 | } 78 | 79 | #cnav > ul > li > a:hover 80 | { 81 | background-color: #70574b; 82 | } 83 | 84 | .code:hover 85 | { 86 | background-color: #8c4e38; 87 | } 88 | 89 | .avro:hover 90 | { 91 | background-color: #c44430; 92 | } 93 | 94 | #home 95 | { 96 | display: table-cell; 97 | width: 1343px; 98 | 99 | vertical-align: middle; 100 | margin: 0px auto; 101 | text-align: center; 102 | 103 | } 104 | #why 105 | { 106 | display: table; 107 | width: 1343px; 108 | 109 | vertical-align: middle; 110 | margin: 0px auto; 111 | text-align: center; 112 | 113 | } 114 | #contact 115 | { 116 | display: table; 117 | width: 1343px; 118 | 119 | vertical-align: middle; 120 | margin: 0px auto; 121 | text-align: center; 122 | } 123 | 124 | div.inner { 125 | display: inline-block; 126 | width: 900px; 127 | height: 470px; 128 | border: 4px solid #8c7468; 129 | 130 | } 131 | 132 | div.inner2 { 133 | margin-top: 100px; 134 | display: inline-block; 135 | width: 1200px; 136 | height: 450px; 137 | border: 4px solid #8c7468; 138 | 139 | } 140 | 141 | div.inner3 { 142 | margin-top: 100px; 143 | display: inline-block; 144 | width: 900px; 145 | height: 450px; 146 | border: 4px solid #8c7468; 147 | 148 | } 149 | 150 | div >.inner > .block 151 | { 152 | margin-top: 1px; 153 | background: #dddddd; 154 | height:462px; 155 | opacity: 0.70; 156 | filter:Alpha(opacity=70); 157 | } 158 | 159 | div >.inner2 > .block2 160 | { 161 | margin-top: 1px; 162 | background: #dddddd; 163 | height:442px; 164 | opacity: 0.70; 165 | filter:Alpha(opacity=70); 166 | } 167 | 168 | div >.inner3 > .block3 169 | { 170 | margin-top: 1px; 171 | background: #dddddd; 172 | height:442px; 173 | opacity: 0.70; 174 | filter:Alpha(opacity=70); 175 | } 176 | 177 | .inblock2 178 | { 179 | padding-top: 75px; 180 | } 181 | 182 | .img > img 183 | { 184 | margin-left:10px; 185 | } 186 | 187 | .hbtn 188 | { 189 | margin-top: 20px; 190 | margin-left: 15px; 191 | } 192 | 193 | .hbtn > div > a 194 | { 195 | padding:15px 25px; 196 | color:#ffffff; 197 | font-size: 1.1em; 198 | font-weight: bold; 199 | border-radius: 3px; 200 | } 201 | .code 202 | { 203 | background-color: #7d3d35; 204 | } 205 | 206 | .avro 207 | { 208 | background-color: #ae302d; 209 | } 210 | 211 | -------------------------------------------------------------------------------- /css/jquery-linedtextarea.css: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Lined Textarea Plugin 3 | * http://alan.blog-city.com/jquerylinedtextarea.htm 4 | * 5 | * Copyright (c) 2010 Alan Williamson 6 | * 7 | * Released under the MIT License: 8 | * http://www.opensource.org/licenses/mit-license.php 9 | * 10 | * Usage: 11 | * Displays a line number count column to the left of the textarea 12 | * 13 | * Class up your textarea with a given class, or target it directly 14 | * with JQuery Selectors 15 | * 16 | * $(".lined").linedtextarea({ 17 | * selectedLine: 10, 18 | * selectedClass: 'lineselect' 19 | * }); 20 | * 21 | */ 22 | 23 | .linedwrap { 24 | border: 1px solid #c0c0c0; 25 | padding: 3px; 26 | } 27 | 28 | .linedtextarea { 29 | padding: 0px; 30 | margin: 0px; 31 | } 32 | 33 | .linedtextarea textarea, .linedwrap .codelines .lineno { 34 | font-size: 10pt; 35 | font-family: monospace; 36 | line-height: normal !important; 37 | } 38 | 39 | .linedtextarea textarea { 40 | padding-right:0.3em; 41 | padding-top:0.3em; 42 | border: 0; 43 | } 44 | 45 | .linedwrap .lines { 46 | margin-top: 0px; 47 | width: 50px; 48 | float: left; 49 | overflow: hidden; 50 | border-right: 1px solid #c0c0c0; 51 | margin-right: 10px; 52 | } 53 | 54 | .linedwrap .codelines { 55 | padding-top: 5px; 56 | } 57 | 58 | .linedwrap .codelines .lineno { 59 | color:#67a321; 60 | padding-right: 0.5em; 61 | padding-top: 0.0em; 62 | text-align: right; 63 | white-space: nowrap; 64 | } 65 | 66 | .linedwrap .codelines .lineselect { 67 | color: #67a321; 68 | } -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | background: url('bck.png'); 4 | background-attachment:fixed; 5 | background-color: #c3b68a; 6 | min-height: 100%; 7 | display: inline-block; 8 | margin: 0px auto; 9 | text-align: center; 10 | } 11 | 12 | a 13 | { 14 | text-decoration: none !important; 15 | } 16 | 17 | 18 | .container-non-responsive { 19 | 20 | /* Set width to your desired site width */ 21 | width: 1343px; 22 | } 23 | .logo 24 | { 25 | margin-left: 25px; 26 | } 27 | .cnav 28 | { 29 | height: 45px; 30 | text-align: left; 31 | background-color: #8c7468; 32 | -webkit-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 33 | -moz-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 34 | box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 35 | } 36 | 37 | .cnav ul 38 | { 39 | margin:0; 40 | list-style: none; 41 | height:45px; 42 | } 43 | 44 | .cnav ul li 45 | { 46 | display:inline-table; 47 | } 48 | 49 | 50 | .cnav > ul > li > a 51 | { 52 | margin:0; 53 | height:40px; 54 | line-height: 40px; 55 | font-size: 97%; 56 | display:inline-table; 57 | padding: 0px 12px; 58 | padding-top: 5px; 59 | color:#ffffff; 60 | 61 | } 62 | 63 | .cnav > ul > li > a:hover 64 | { 65 | background-color: #70574b; 66 | } 67 | 68 | .enav 69 | { 70 | height: 35px; 71 | max-width: 100%; 72 | text-align: left; 73 | background-color: #ffffff; 74 | opacity: 0.82; 75 | filter:Alpha(opacity=82); 76 | 77 | } 78 | .enav ul 79 | { 80 | margin:0; 81 | list-style: none; 82 | height:30px; 83 | } 84 | 85 | .enav ul li 86 | { 87 | display:inline-table; 88 | } 89 | 90 | 91 | .enav > div> ul > li > a 92 | { 93 | margin:0; 94 | height:35px; 95 | line-height: 35px; 96 | font-size: 97%; 97 | display:inline-table; 98 | padding: 0px 3px; 99 | padding-top: 0px; 100 | color:#788f85; 101 | 102 | } 103 | 104 | .enav > div> ul > a 105 | { 106 | margin:0; 107 | height:24px; 108 | line-height: 24px; 109 | font-size: 90%; 110 | display:inline-table; 111 | padding: 0px 7px; 112 | padding-top: 0px; 113 | color:#ffffff; 114 | background-color:#788f85; 115 | border-radius: 3px; 116 | } 117 | 118 | .enav > ul> a 119 | { 120 | margin:0; 121 | height:24px; 122 | line-height: 24px; 123 | font-size: 90%; 124 | display:inline-table; 125 | padding: 0px 7px; 126 | margin-top: 6px; 127 | color:#ffffff; 128 | background-color:#788f85; 129 | border-radius: 3px; 130 | } 131 | 132 | .first 133 | { 134 | margin-top: 25px; 135 | margin-left: 15px; 136 | } 137 | 138 | .first-right 139 | { 140 | margin-left: 40px; 141 | } 142 | 143 | .navcode 144 | { 145 | margin-bottom: 3px; 146 | } 147 | 148 | /*.linedwrap 149 | { 150 | border-top: 25px solid #92d050; 151 | border-radius: 7px 7px 0 0; 152 | }*/ 153 | 154 | /*.result 155 | { 156 | border-top: 25px solid #ffbb1e; 157 | border-radius: 7px 7px 0 0; 158 | }*/ 159 | 160 | .codelines 161 | { 162 | background: #ffffff; 163 | opacity: 0.82; 164 | filter:Alpha(opacity=82); 165 | } 166 | 167 | .linedwrap .codelines .lineno 168 | { 169 | color:#788f85; 170 | } 171 | 172 | textarea 173 | { 174 | background:#ffffff; 175 | opacity: 0.82; 176 | filter:Alpha(opacity=82); 177 | } 178 | 179 | .btitle 180 | { 181 | padding-top: 8px; 182 | color:#788f85; 183 | font-weight:bold; 184 | } 185 | 186 | .run 187 | { 188 | height:24px !important; 189 | } 190 | 191 | .second 192 | { 193 | margin-left: 15px; 194 | margin-top: 3px; 195 | background-color: #ffffff; 196 | opacity: 0.82; 197 | filter:Alpha(opacity=82); 198 | -webkit-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 199 | -moz-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 200 | box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 201 | } 202 | 203 | .enav > ul > a 204 | { 205 | background-color: #8c7468; 206 | } 207 | .enav > ul > p 208 | { 209 | height:24px; 210 | line-height: 35px; 211 | padding-left: 10px; 212 | color: #6b594f; 213 | } 214 | 215 | .keywords 216 | { 217 | margin:18px 0; 218 | width:450px !important; 219 | 220 | } 221 | .keywords > div 222 | { 223 | text-align: center; 224 | } 225 | 226 | .keywords > div > a 227 | { 228 | padding:6px; 229 | color:#ffffff; 230 | border-radius: 3px; 231 | font-size: 85%; 232 | } 233 | .a 234 | { 235 | background-color: #596a63; 236 | } 237 | .b 238 | { 239 | background-color: #a58645; 240 | } 241 | .c 242 | { 243 | background-color: #6b594f; 244 | } 245 | .d 246 | { 247 | background-color: #7d3d35; 248 | } 249 | 250 | #home 251 | { 252 | height:768px; 253 | 254 | } 255 | #why 256 | { 257 | height:768px; 258 | 259 | } 260 | #contact 261 | { 262 | height:768px; 263 | } 264 | 265 | 266 | .bottom 267 | { 268 | margin-top: 3px; 269 | background-color:#ffffff; 270 | opacity: 0.82; 271 | filter:Alpha(opacity=82); 272 | 273 | -webkit-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 274 | -moz-box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 275 | box-shadow: 1px 1px 11px 0px rgba(50, 50, 50, 0.68); 276 | } 277 | 278 | .tooltip-inner 279 | { 280 | background-color: #6b594f; 281 | } 282 | 283 | .customtheme1 { 284 | border: 5px solid #6b594f; 285 | } 286 | 287 | .customtheme2 { 288 | border: 5px solid #a58645; 289 | } 290 | 291 | .customtheme3 { 292 | border: 5px solid #596a63; 293 | } 294 | 295 | .customtheme4 { 296 | border: 5px solid #7d3d35; 297 | } 298 | 299 | #loading { 300 | width: 100%; 301 | height: 100%; 302 | top: 0px; 303 | left: 0px; 304 | position: fixed; 305 | display: block; 306 | opacity: 0.7; 307 | background-color: #fff; 308 | z-index: 99; 309 | text-align: center; 310 | } 311 | 312 | #loading-image { 313 | position: absolute; 314 | top: 100px; 315 | left: 500px; 316 | z-index: 100; 317 | } -------------------------------------------------------------------------------- /css/tooltipster-light.css: -------------------------------------------------------------------------------- 1 | .tooltipster-light { 2 | border-radius: 5px; 3 | border: 1px solid #cccccc; 4 | background: #ededed; 5 | color: #666666; 6 | } 7 | .tooltipster-light .tooltipster-content { 8 | font-family: Arial, sans-serif; 9 | font-size: 14px; 10 | line-height: 16px; 11 | padding: 8px 10px; 12 | } -------------------------------------------------------------------------------- /css/tooltipster.css: -------------------------------------------------------------------------------- 1 | /* This is the default Tooltipster theme (feel free to modify or duplicate and create multiple themes!): */ 2 | .tooltipster-default { 3 | border-radius: 5px; 4 | border: 2px solid #000; 5 | background: #4c4c4c; 6 | color: #fff; 7 | } 8 | 9 | /* Use this next selector to style things like font-size and line-height: */ 10 | .tooltipster-default .tooltipster-content { 11 | font-family: Arial, sans-serif; 12 | font-size: 14px; 13 | line-height: 16px; 14 | padding: 8px 10px; 15 | overflow: hidden; 16 | } 17 | 18 | /* This next selector defines the color of the border on the outside of the arrow. This will automatically match the color and size of the border set on the main tooltip styles. Set display: none; if you would like a border around the tooltip but no border around the arrow */ 19 | .tooltipster-default .tooltipster-arrow .tooltipster-arrow-border { 20 | /* border-color: ... !important; */ 21 | } 22 | 23 | 24 | /* If you're using the icon option, use this next selector to style them */ 25 | .tooltipster-icon { 26 | cursor: help; 27 | margin-left: 4px; 28 | } 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | /* This is the base styling required to make all Tooltipsters work */ 38 | .tooltipster-base { 39 | padding: 0; 40 | font-size: 0; 41 | line-height: 0; 42 | position: absolute; 43 | left: 0; 44 | top: 0; 45 | z-index: 9999999; 46 | pointer-events: none; 47 | width: auto; 48 | overflow: visible; 49 | } 50 | .tooltipster-base .tooltipster-content { 51 | overflow: hidden; 52 | } 53 | 54 | 55 | /* These next classes handle the styles for the little arrow attached to the tooltip. By default, the arrow will inherit the same colors and border as what is set on the main tooltip itself. */ 56 | .tooltipster-arrow { 57 | display: block; 58 | text-align: center; 59 | width: 100%; 60 | height: 100%; 61 | position: absolute; 62 | top: 0; 63 | left: 0; 64 | z-index: -1; 65 | } 66 | .tooltipster-arrow span, .tooltipster-arrow-border { 67 | display: block; 68 | width: 0; 69 | height: 0; 70 | position: absolute; 71 | } 72 | .tooltipster-arrow-top span, .tooltipster-arrow-top-right span, .tooltipster-arrow-top-left span { 73 | border-left: 8px solid transparent !important; 74 | border-right: 8px solid transparent !important; 75 | border-top: 8px solid; 76 | bottom: -7px; 77 | } 78 | .tooltipster-arrow-top .tooltipster-arrow-border, .tooltipster-arrow-top-right .tooltipster-arrow-border, .tooltipster-arrow-top-left .tooltipster-arrow-border { 79 | border-left: 9px solid transparent !important; 80 | border-right: 9px solid transparent !important; 81 | border-top: 9px solid; 82 | bottom: -7px; 83 | } 84 | 85 | .tooltipster-arrow-bottom span, .tooltipster-arrow-bottom-right span, .tooltipster-arrow-bottom-left span { 86 | border-left: 8px solid transparent !important; 87 | border-right: 8px solid transparent !important; 88 | border-bottom: 8px solid; 89 | top: -7px; 90 | } 91 | .tooltipster-arrow-bottom .tooltipster-arrow-border, .tooltipster-arrow-bottom-right .tooltipster-arrow-border, .tooltipster-arrow-bottom-left .tooltipster-arrow-border { 92 | border-left: 9px solid transparent !important; 93 | border-right: 9px solid transparent !important; 94 | border-bottom: 9px solid; 95 | top: -7px; 96 | } 97 | .tooltipster-arrow-top span, .tooltipster-arrow-top .tooltipster-arrow-border, .tooltipster-arrow-bottom span, .tooltipster-arrow-bottom .tooltipster-arrow-border { 98 | left: 0; 99 | right: 0; 100 | margin: 0 auto; 101 | } 102 | .tooltipster-arrow-top-left span, .tooltipster-arrow-bottom-left span { 103 | left: 6px; 104 | } 105 | .tooltipster-arrow-top-left .tooltipster-arrow-border, .tooltipster-arrow-bottom-left .tooltipster-arrow-border { 106 | left: 5px; 107 | } 108 | .tooltipster-arrow-top-right span, .tooltipster-arrow-bottom-right span { 109 | right: 6px; 110 | } 111 | .tooltipster-arrow-top-right .tooltipster-arrow-border, .tooltipster-arrow-bottom-right .tooltipster-arrow-border { 112 | right: 5px; 113 | } 114 | .tooltipster-arrow-left span, .tooltipster-arrow-left .tooltipster-arrow-border { 115 | border-top: 8px solid transparent !important; 116 | border-bottom: 8px solid transparent !important; 117 | border-left: 8px solid; 118 | top: 50%; 119 | margin-top: -7px; 120 | right: -7px; 121 | } 122 | .tooltipster-arrow-left .tooltipster-arrow-border { 123 | border-top: 9px solid transparent !important; 124 | border-bottom: 9px solid transparent !important; 125 | border-left: 9px solid; 126 | margin-top: -8px; 127 | } 128 | .tooltipster-arrow-right span, .tooltipster-arrow-right .tooltipster-arrow-border { 129 | border-top: 8px solid transparent !important; 130 | border-bottom: 8px solid transparent !important; 131 | border-right: 8px solid; 132 | top: 50%; 133 | margin-top: -7px; 134 | left: -7px; 135 | } 136 | .tooltipster-arrow-right .tooltipster-arrow-border { 137 | border-top: 9px solid transparent !important; 138 | border-bottom: 9px solid transparent !important; 139 | border-right: 9px solid; 140 | margin-top: -8px; 141 | } 142 | 143 | 144 | /* Some CSS magic for the awesome animations - feel free to make your own custom animations and reference it in your Tooltipster settings! */ 145 | 146 | .tooltipster-fade { 147 | opacity: 0; 148 | -webkit-transition-property: opacity; 149 | -moz-transition-property: opacity; 150 | -o-transition-property: opacity; 151 | -ms-transition-property: opacity; 152 | transition-property: opacity; 153 | } 154 | .tooltipster-fade-show { 155 | opacity: 1; 156 | } 157 | 158 | .tooltipster-grow { 159 | -webkit-transform: scale(0,0); 160 | -moz-transform: scale(0,0); 161 | -o-transform: scale(0,0); 162 | -ms-transform: scale(0,0); 163 | transform: scale(0,0); 164 | -webkit-transition-property: -webkit-transform; 165 | -moz-transition-property: -moz-transform; 166 | -o-transition-property: -o-transform; 167 | -ms-transition-property: -ms-transform; 168 | transition-property: transform; 169 | -webkit-backface-visibility: hidden; 170 | } 171 | .tooltipster-grow-show { 172 | -webkit-transform: scale(1,1); 173 | -moz-transform: scale(1,1); 174 | -o-transform: scale(1,1); 175 | -ms-transform: scale(1,1); 176 | transform: scale(1,1); 177 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 178 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 179 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 180 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 181 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 182 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 183 | } 184 | 185 | .tooltipster-swing { 186 | opacity: 0; 187 | -webkit-transform: rotateZ(4deg); 188 | -moz-transform: rotateZ(4deg); 189 | -o-transform: rotateZ(4deg); 190 | -ms-transform: rotateZ(4deg); 191 | transform: rotateZ(4deg); 192 | -webkit-transition-property: -webkit-transform, opacity; 193 | -moz-transition-property: -moz-transform; 194 | -o-transition-property: -o-transform; 195 | -ms-transition-property: -ms-transform; 196 | transition-property: transform; 197 | } 198 | .tooltipster-swing-show { 199 | opacity: 1; 200 | -webkit-transform: rotateZ(0deg); 201 | -moz-transform: rotateZ(0deg); 202 | -o-transform: rotateZ(0deg); 203 | -ms-transform: rotateZ(0deg); 204 | transform: rotateZ(0deg); 205 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 1); 206 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 207 | -moz-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 208 | -ms-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 209 | -o-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 210 | transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 211 | } 212 | 213 | .tooltipster-fall { 214 | top: 0; 215 | -webkit-transition-property: top; 216 | -moz-transition-property: top; 217 | -o-transition-property: top; 218 | -ms-transition-property: top; 219 | transition-property: top; 220 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 221 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 222 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 223 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 224 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 225 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 226 | } 227 | .tooltipster-fall-show { 228 | } 229 | .tooltipster-fall.tooltipster-dying { 230 | -webkit-transition-property: all; 231 | -moz-transition-property: all; 232 | -o-transition-property: all; 233 | -ms-transition-property: all; 234 | transition-property: all; 235 | top: 0px !important; 236 | opacity: 0; 237 | } 238 | 239 | .tooltipster-slide { 240 | left: -40px; 241 | -webkit-transition-property: left; 242 | -moz-transition-property: left; 243 | -o-transition-property: left; 244 | -ms-transition-property: left; 245 | transition-property: left; 246 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 247 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 248 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 249 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 250 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 251 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 252 | } 253 | .tooltipster-slide.tooltipster-slide-show { 254 | } 255 | .tooltipster-slide.tooltipster-dying { 256 | -webkit-transition-property: all; 257 | -moz-transition-property: all; 258 | -o-transition-property: all; 259 | -ms-transition-property: all; 260 | transition-property: all; 261 | left: 0px !important; 262 | opacity: 0; 263 | } 264 | 265 | 266 | /* CSS transition for when contenting is changing in a tooltip that is still open. The only properties that will NOT transition are: width, height, top, and left */ 267 | .tooltipster-content-changing { 268 | opacity: 0.5; 269 | -webkit-transform: scale(1.1, 1.1); 270 | -moz-transform: scale(1.1, 1.1); 271 | -o-transform: scale(1.1, 1.1); 272 | -ms-transform: scale(1.1, 1.1); 273 | transform: scale(1.1, 1.1); 274 | } 275 | -------------------------------------------------------------------------------- /examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | চা Script - Examples 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 35 | 36 | 37 |
38 | 39 |

Hello World

40 |

41 | দেখাও("হ্যালো ওয়ার্ল্ড") 42 |

43 |
44 | 45 |

I/O (Scanf Printf)

46 |

47 | ক = নাও("আপনার নাম লিখুন")
48 | দেখাও( "আপনার নাম " + ক)
49 |

50 |
51 | 52 |

Basic Arithmetic

53 |

54 | ক = ১০
55 | খ = ২
56 | গ = ৩
57 | ঘ = ৪
58 | চ = ক / খ - গ * ঘ
59 | দেখাও( চ)
60 |

61 |
62 |

If Condition

63 |

64 | ক = ১৫
65 | যদি( ক < ৫ )
66 | {
67 | দেখাও( "ক এর মান ৫ থেকে কম ।ন")
68 | }
নাহলে 69 | {
70 | দেখাও("ক এর মান ৫ থেকে বেশী")
71 | } 72 | 73 |

74 | 75 |
76 | 77 |

Loop (।ন = New Line)

78 |

79 | ক = ১
80 | চলবে
81 | {
82 | যদি(ক > ১০)
83 | {
84 | থামো
85 | }
86 | দেখাও(ক + "।ন")
87 | ক = ক + ১
88 | } 89 |

90 |
91 | 92 |

String Search

93 |

94 | ক= "আম আপেল কাঁঠাল"
95 | গ = কঃআছে("আপেল")
96 | যদি(গ != -১)
97 | {
98 | দেখাও("আপেল আছে")
99 | } 100 |

101 | 102 |
103 | 104 |

Maximum Number in Array

105 |

106 | ক = সেট(১,৩,৭,২)
107 | ব = ক[০]
108 | ত = ১
109 | চলবে
110 | {
111 | যদি(ব <= ক[ত])
112 | {
113 | ব = ক[ত]
114 | }
115 | ত = ত + ১
116 | যদি(ত==কঃআয়তন)
117 | {
118 | থামো
119 | }
120 | }
121 | দেখাও(ব) 122 |

123 |
124 | 125 | 134 | -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /images/Picture1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/Picture1.png -------------------------------------------------------------------------------- /images/acche.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/acche.png -------------------------------------------------------------------------------- /images/ayoton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/ayoton.png -------------------------------------------------------------------------------- /images/baad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/baad.png -------------------------------------------------------------------------------- /images/cholbe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/cholbe.png -------------------------------------------------------------------------------- /images/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/contact.png -------------------------------------------------------------------------------- /images/dekhao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/dekhao.png -------------------------------------------------------------------------------- /images/favicon - Copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/favicon - Copy.png -------------------------------------------------------------------------------- /images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/favicon.png -------------------------------------------------------------------------------- /images/function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/function.png -------------------------------------------------------------------------------- /images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/home.png -------------------------------------------------------------------------------- /images/hometext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/hometext.png -------------------------------------------------------------------------------- /images/jodi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/jodi.png -------------------------------------------------------------------------------- /images/loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/loader.png -------------------------------------------------------------------------------- /images/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/logo2.png -------------------------------------------------------------------------------- /images/nahole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/nahole.png -------------------------------------------------------------------------------- /images/nao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/nao.png -------------------------------------------------------------------------------- /images/rakho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/rakho.png -------------------------------------------------------------------------------- /images/set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/set.png -------------------------------------------------------------------------------- /images/shorao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/shorao.png -------------------------------------------------------------------------------- /images/shorto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/shorto.png -------------------------------------------------------------------------------- /images/songkha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/songkha.png -------------------------------------------------------------------------------- /images/thamo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/thamo.png -------------------------------------------------------------------------------- /images/uttor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjishan/chascript/c94b9984da30b7310e90b5d45415b70faffb6eef/images/uttor.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | চা Script - Home 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 48 | 49 | 50 | 51 | 52 | 53 | 66 | 67 |
68 | 69 | 70 | 71 |
72 |
73 | 81 | 82 |
83 | 84 |
85 |
86 |
87 |
88 |
89 | Home 90 |
91 | 95 | 96 |
97 |
98 | Home 99 |
100 |
101 |
102 |
*চা Script is totally depended on the grammar of ECMA Script which is parsed using Jison
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | 113 |
114 |
115 |

Easy to Learn

116 |

চা Script was designed as a learning platform for computer programming. It can be a stepping stone for people to learn how to code but thinks language can be a barrier for them to learn something new and that is why we developed চা Script, a বাংলা scripting language with well documentation and tutorials.

117 |
118 |
119 |
120 |
121 | 122 |
123 |
124 |

Easy to Code

125 |

চা Script contains primitive and easy syntax definitions. No need for type declaration. No need for semicolons. An integrated coding enviroment is provided with keyword buttons for the ease of writing codes.

126 |
127 |
128 |
129 |
130 | 131 |
132 |
133 |

No Installation Required

134 |

চা Script do not need any kind of installation process. It is a fully web based scripting language which can also be used in offline mode if the files are downloaded in the local server/pc.However, we encourage users to download Avro Keyboard to write বাংলা.

135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | Contact Us 145 |
146 |
147 |
148 |

Md. Nuruddin Monsur

Email: get2adnan@windowslive.com

149 |

Arman Kamal

Email: arman1790@gmail.com

150 |

Syed Tanveer Jishan

Email: tanveer_syed@live.com

151 |

Fahad Billah

Email: billah22@gmail.com

152 |

Mursalin Kabir

Email: mail2mursalin@gmail.com

153 |
154 |
155 |
156 |
157 |
158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /indextest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | চা Script - Home 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 48 | 49 | 50 | 51 | 52 | 53 |
54 | 67 |
68 | 69 | 70 |
71 | 72 |
73 |
74 |
75 |
76 |
77 | Home 78 |
79 | 83 | 84 |
85 |
86 | Home 87 |
88 |
89 |
90 |
*চা Script is totally depended on the grammar of ECMA Script which is parsed using Jison
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | 101 |
102 |
103 |

Easy to Learn

104 |

চা Script was designed as a learning platform for computer programming. It can be a stepping stone for people to learn how to code but thinks language can be a barrier for them to learn something new and that is why we developed চা Script, a বাংলা scripting language with well documentation and tutorials.

105 |
106 |
107 |
108 |
109 | 110 |
111 |
112 |

Easy to Code

113 |

চা Script contains primitive and easy syntax definitions. No need for type declaration. No need for semicolons. An integrated coding enviroment is provided with keyword buttons for the ease of writing codes.

114 |
115 |
116 |
117 |
118 | 119 |
120 |
121 |

No Installation Required

122 |

চা Script do not need any kind of installation process. It is a fully web based scripting language which can also be used in offline mode if the files are downloaded in the local server/pc.However, we encourage users to download Avro Keyboard to write বাংলা.

123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | Contact Us 132 |
133 |
134 |
135 |

Md. Nuruddin Monsur

Email: get2adnan@windowslive.com

136 |

Arman Kamal

Email: arman1790@gmail.com

137 |

Syed Tanveer Jishan

Email: tanveer_syed@live.com

138 |

Fahad Billah

Email: billah22@gmail.com

139 |
140 |
141 |
142 |
143 |
144 |
145 | 146 | 147 |
148 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /jquery-linedtextarea.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JQuery LinedTextArea Demo 4 | 5 | 6 | 7 | 8 | 9 | 10 |

JQuery LinedTextArea Demo

11 | 12 |

Add a scrollable lined area to a standard TextArea control.

13 | 14 | 34 | 35 | 42 | 43 |

Visit http://alan.blog-city.com/jquerylinedtextarea.htm for details and download

44 | 45 | 46 | -------------------------------------------------------------------------------- /js/base64.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Base64 encode / decode 4 | * http://www.webtoolkit.info/ 5 | * 6 | **/ 7 | 8 | var Base64 = { 9 | 10 | // private property 11 | _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 12 | 13 | // public method for encoding 14 | encode : function (input) { 15 | var output = ""; 16 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 17 | var i = 0; 18 | 19 | input = Base64._utf8_encode(input); 20 | 21 | while (i < input.length) { 22 | 23 | chr1 = input.charCodeAt(i++); 24 | chr2 = input.charCodeAt(i++); 25 | chr3 = input.charCodeAt(i++); 26 | 27 | enc1 = chr1 >> 2; 28 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 29 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 30 | enc4 = chr3 & 63; 31 | 32 | if (isNaN(chr2)) { 33 | enc3 = enc4 = 64; 34 | } else if (isNaN(chr3)) { 35 | enc4 = 64; 36 | } 37 | 38 | output = output + 39 | this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + 40 | this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); 41 | 42 | } 43 | 44 | return output; 45 | }, 46 | 47 | // public method for decoding 48 | decode : function (input) { 49 | var output = ""; 50 | var chr1, chr2, chr3; 51 | var enc1, enc2, enc3, enc4; 52 | var i = 0; 53 | 54 | input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 55 | 56 | while (i < input.length) { 57 | 58 | enc1 = this._keyStr.indexOf(input.charAt(i++)); 59 | enc2 = this._keyStr.indexOf(input.charAt(i++)); 60 | enc3 = this._keyStr.indexOf(input.charAt(i++)); 61 | enc4 = this._keyStr.indexOf(input.charAt(i++)); 62 | 63 | chr1 = (enc1 << 2) | (enc2 >> 4); 64 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 65 | chr3 = ((enc3 & 3) << 6) | enc4; 66 | 67 | output = output + String.fromCharCode(chr1); 68 | 69 | if (enc3 != 64) { 70 | output = output + String.fromCharCode(chr2); 71 | } 72 | if (enc4 != 64) { 73 | output = output + String.fromCharCode(chr3); 74 | } 75 | 76 | } 77 | 78 | output = Base64._utf8_decode(output); 79 | 80 | return output; 81 | 82 | }, 83 | 84 | // private method for UTF-8 encoding 85 | _utf8_encode : function (string) { 86 | string = string.replace(/\r\n/g,"\n"); 87 | var utftext = ""; 88 | 89 | for (var n = 0; n < string.length; n++) { 90 | 91 | var c = string.charCodeAt(n); 92 | 93 | if (c < 128) { 94 | utftext += String.fromCharCode(c); 95 | } 96 | else if((c > 127) && (c < 2048)) { 97 | utftext += String.fromCharCode((c >> 6) | 192); 98 | utftext += String.fromCharCode((c & 63) | 128); 99 | } 100 | else { 101 | utftext += String.fromCharCode((c >> 12) | 224); 102 | utftext += String.fromCharCode(((c >> 6) & 63) | 128); 103 | utftext += String.fromCharCode((c & 63) | 128); 104 | } 105 | 106 | } 107 | 108 | return utftext; 109 | }, 110 | 111 | // private method for UTF-8 decoding 112 | _utf8_decode : function (utftext) { 113 | var string = ""; 114 | var i = 0; 115 | var c = c1 = c2 = 0; 116 | 117 | while ( i < utftext.length ) { 118 | 119 | c = utftext.charCodeAt(i); 120 | 121 | if (c < 128) { 122 | string += String.fromCharCode(c); 123 | i++; 124 | } 125 | else if((c > 191) && (c < 224)) { 126 | c2 = utftext.charCodeAt(i+1); 127 | string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); 128 | i += 2; 129 | } 130 | else { 131 | c2 = utftext.charCodeAt(i+1); 132 | c3 = utftext.charCodeAt(i+2); 133 | string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); 134 | i += 3; 135 | } 136 | 137 | } 138 | 139 | return string; 140 | } 141 | 142 | } -------------------------------------------------------------------------------- /js/formState.js: -------------------------------------------------------------------------------- 1 | /* 2 | Form State v 1.2 3 | copyright 2007 Thomas Frank 4 | 5 | This program is free software under the terms of the 6 | GNU General Public License version 2 as published by the Free 7 | Software Foundation. It is distributed without any warranty. 8 | */ 9 | formState={ 10 | eventsBeforeStore:true, 11 | onStateChange:false, 12 | init:function(){ 13 | // add to onload 14 | if(!formState.onloadAdded){ 15 | formState.onloadAdded=true; 16 | (function(){var ol=onload;onload=function(){if(ol){ol()};formState.init()}})(); 17 | return 18 | }; 19 | // modify/create event handlers on all form elements 20 | var f=document.forms 21 | for(var i=0;i=0; 24 | f[i].id=f[i].id.replace(/_undoable/,'').replace(/_keystroke/,''); 25 | var e=f[i].elements; 26 | for(var j=0;jf.formStateCo){f.formStateMem.pop()}; 60 | f.formStateMem[f.formStateCo]=a; 61 | this.checkQueue(f) 62 | }, 63 | readBack:function(f,a){ 64 | // read back values to form and check if different 65 | var fe=f.elements, ae=a.elements, d=false; 66 | for(var i=0;i1; 81 | var redoable=f.formStateMem.length-f.formStateCo>1; 82 | if(f.elements.Undo){f.elements.Undo.disabled=!undoable}; 83 | if(f.elements.Redo){f.elements.Redo.disabled=!redoable}; 84 | if(this.onStateChange){this.onStateChange(f,undoable,redoable)} 85 | }, 86 | undo:function(a,r){ 87 | if(!r){r=-1}; 88 | var tN=a.tagName.toLowerCase()||""; 89 | if(a.parentNode && tN!="form"){a=a.parentNode;return this.undo(a,r)}; 90 | if(!a.formStateMem){return false}; 91 | var f=a.formStateMem[a.formStateCo+r]; 92 | if(!f){return false}; 93 | a.formStateCo+=r; 94 | if(!this.readBack(f,a)){return this.undo(a,r)}; 95 | this.checkQueue(a); 96 | return true 97 | }, 98 | redo:function(a){return this.undo(a,1)} 99 | }; 100 | formState.init(); -------------------------------------------------------------------------------- /js/jquery-linedtextarea.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Lined Textarea Plugin 3 | * http://alan.blog-city.com/jquerylinedtextarea.htm 4 | * 5 | * Copyright (c) 2010 Alan Williamson 6 | * 7 | * Version: 8 | * $Id: jquery-linedtextarea.js 464 2010-01-08 10:36:33Z alan $ 9 | * 10 | * Released under the MIT License: 11 | * http://www.opensource.org/licenses/mit-license.php 12 | * 13 | * Usage: 14 | * Displays a line number count column to the left of the textarea 15 | * 16 | * Class up your textarea with a given class, or target it directly 17 | * with JQuery Selectors 18 | * 19 | * $(".lined").linedtextarea({ 20 | * selectedLine: 10, 21 | * selectedClass: 'lineselect' 22 | * }); 23 | * 24 | * History: 25 | * - 2010.01.08: Fixed a Google Chrome layout problem 26 | * - 2010.01.07: Refactored code for speed/readability; Fixed horizontal sizing 27 | * - 2010.01.06: Initial Release 28 | * 29 | */ 30 | (function($) { 31 | 32 | $.fn.linedtextarea = function(options) { 33 | 34 | // Get the Options 35 | var opts = $.extend({}, $.fn.linedtextarea.defaults, options); 36 | 37 | 38 | /* 39 | * Helper function to make sure the line numbers are always 40 | * kept up to the current system 41 | */ 42 | var fillOutLines = function(codeLines, h, lineNo){ 43 | while ( (codeLines.height() - h ) <= 0 ){ 44 | if ( lineNo == opts.selectedLine ) 45 | codeLines.append("
" + lineNo + "
"); 46 | else 47 | codeLines.append("
" + lineNo + "
"); 48 | 49 | lineNo++; 50 | } 51 | return lineNo; 52 | }; 53 | 54 | 55 | /* 56 | * Iterate through each of the elements are to be applied to 57 | */ 58 | return this.each(function() { 59 | var lineNo = 1; 60 | var textarea = $(this); 61 | 62 | /* Turn off the wrapping of as we don't want to screw up the line numbers */ 63 | textarea.attr("wrap", "off"); 64 | textarea.css({resize:'none'}); 65 | var originalTextAreaWidth = textarea.outerWidth(); 66 | 67 | /* Wrap the text area in the elements we need */ 68 | textarea.wrap("
"); 69 | var linedTextAreaDiv = textarea.parent().wrap("
"); 70 | var linedWrapDiv = linedTextAreaDiv.parent(); 71 | 72 | linedWrapDiv.prepend("
"); 73 | 74 | var linesDiv = linedWrapDiv.find(".lines"); 75 | linesDiv.height( textarea.height() + 6 ); 76 | 77 | 78 | /* Draw the number bar; filling it out where necessary */ 79 | linesDiv.append( "
" ); 80 | var codeLinesDiv = linesDiv.find(".codelines"); 81 | lineNo = fillOutLines( codeLinesDiv, linesDiv.height(), 1 ); 82 | 83 | /* Move the textarea to the selected line */ 84 | if ( opts.selectedLine != -1 && !isNaN(opts.selectedLine) ){ 85 | var fontSize = parseInt( textarea.height() / (lineNo-2) ); 86 | var position = parseInt( fontSize * opts.selectedLine ) - (textarea.height()/2); 87 | textarea[0].scrollTop = position; 88 | } 89 | 90 | 91 | /* Set the width */ 92 | var sidebarWidth = linesDiv.outerWidth(); 93 | var paddingHorizontal = parseInt( linedWrapDiv.css("border-left-width") ) + parseInt( linedWrapDiv.css("border-right-width") ) + parseInt( linedWrapDiv.css("padding-left") ) + parseInt( linedWrapDiv.css("padding-right") ); 94 | var linedWrapDivNewWidth = originalTextAreaWidth - paddingHorizontal; 95 | var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20; 96 | 97 | textarea.width( textareaNewWidth ); 98 | linedWrapDiv.width( linedWrapDivNewWidth ); 99 | 100 | 101 | 102 | /* React to the scroll event */ 103 | textarea.scroll( function(tn){ 104 | var domTextArea = $(this)[0]; 105 | var scrollTop = domTextArea.scrollTop; 106 | var clientHeight = domTextArea.clientHeight; 107 | codeLinesDiv.css( {'margin-top': (-1*scrollTop) + "px"} ); 108 | lineNo = fillOutLines( codeLinesDiv, scrollTop + clientHeight, lineNo ); 109 | }); 110 | 111 | 112 | /* Should the textarea get resized outside of our control */ 113 | textarea.resize( function(tn){ 114 | var domTextArea = $(this)[0]; 115 | linesDiv.height( domTextArea.clientHeight + 6 ); 116 | }); 117 | 118 | }); 119 | }; 120 | 121 | // default options 122 | $.fn.linedtextarea.defaults = { 123 | selectedLine: -1, 124 | selectedClass: 'lineselect' 125 | }; 126 | })(jQuery); -------------------------------------------------------------------------------- /js/jquery.a-tools-1.4.1.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * a-tools 1.4.1 3 | * 4 | * Copyright (c) 2009 Andrey Kramarev(andrey.kramarev[at]ampparit.com), Ampparit Inc. (www.ampparit.com) 5 | * Licensed under the MIT license. 6 | * http://www.ampparit.fi/a-tools/license.txt 7 | * 8 | * Basic usage: 9 | 10 | 11 | 12 | 13 | // Get current selection 14 | var sel = $("textarea").getSelection() 15 | 16 | // Replace current selection 17 | $("input").replaceSelection("foo"); 18 | 19 | // Count characters 20 | alert($("textarea").countCharacters()); 21 | 22 | // Set max length without callback function 23 | $("textarea").setMaxLength(7); 24 | 25 | // Set max length with callback function which will be called when limit is exceeded 26 | $("textarea").setMaxLength(10, function() { 27 | alert("hello") 28 | }); 29 | 30 | // Removing limit: 31 | $("textarea").setMaxLength(-1); 32 | 33 | // Insert text at current caret position 34 | $("#textarea").insertAtCaretPos("hello"); 35 | 36 | // Set caret position (1 = beginning, -1 = end) 37 | $("#textArea").setCaretPos(10); 38 | 39 | // Set Selection 40 | $("#textArea").setSelection(10,15); 41 | 42 | */ 43 | var caretPositionAmp; 44 | 45 | jQuery.fn.extend({ 46 | getSelection: function() { // function for getting selection, and position of the selected text 47 | var input = this.jquery ? this[0] : this; 48 | var start; 49 | var end; 50 | var part; 51 | var number = 0; 52 | input.onmousedown = function() { // for IE because it loses caret position when focus changed 53 | if (document.selection && typeof(input.selectionStart) != "number") { 54 | document.selection.empty(); 55 | } else { 56 | window.getSelection().removeAllRanges(); 57 | } 58 | } 59 | if (document.selection) { 60 | // part for IE and Opera 61 | var s = document.selection.createRange(); 62 | var minus = 0; 63 | var position = 0; 64 | var minusEnd = 0; 65 | var re; 66 | var rc; 67 | if (input.value.match(/\n/g) != null) { 68 | number = input.value.match(/\n/g).length;// number of EOL simbols 69 | } 70 | if (s.text) { 71 | part = s.text; 72 | // OPERA support 73 | if (typeof(input.selectionStart) == "number") { 74 | start = input.selectionStart; 75 | end = input.selectionEnd; 76 | // return null if the selected text not from the needed area 77 | if (start == end) { 78 | return { start: start, end: end, text: s.text, length: end - start }; 79 | } 80 | } else { 81 | // IE support 82 | var firstRe; 83 | var secondRe; 84 | re = input.createTextRange(); 85 | rc = re.duplicate(); 86 | firstRe = re.text; 87 | re.moveToBookmark(s.getBookmark()); 88 | secondRe = re.text; 89 | rc.setEndPoint("EndToStart", re); 90 | // return null if the selectyed text not from the needed area 91 | if (firstRe == secondRe && firstRe != s.text) { 92 | return this; 93 | } 94 | start = rc.text.length; 95 | end = rc.text.length + s.text.length; 96 | } 97 | // remove all EOL to have the same start and end positons as in MOZILLA 98 | if (number > 0) { 99 | for (var i = 0; i <= number; i++) { 100 | var w = input.value.indexOf("\n", position); 101 | if (w != -1 && w < start) { 102 | position = w + 1; 103 | minus++; 104 | minusEnd = minus; 105 | } else if (w != -1 && w >= start && w <= end) { 106 | if (w == start + 1) { 107 | minus--; 108 | minusEnd--; 109 | position = w + 1; 110 | continue; 111 | } 112 | position = w + 1; 113 | minusEnd++; 114 | } else { 115 | i = number; 116 | } 117 | } 118 | } 119 | if (s.text.indexOf("\n", 0) == 1) { 120 | minusEnd = minusEnd + 2; 121 | } 122 | start = start - minus; 123 | end = end - minusEnd; 124 | 125 | return { start: start, end: end, text: s.text, length: end - start }; 126 | } 127 | input.focus (); 128 | if (typeof(input.selectionStart) == "number") { 129 | start = input.selectionStart; 130 | } else { 131 | s = document.selection.createRange(); 132 | re = input.createTextRange(); 133 | rc = re.duplicate(); 134 | re.moveToBookmark(s.getBookmark()); 135 | rc.setEndPoint("EndToStart", re); 136 | start = rc.text.length; 137 | } 138 | if (number > 0) { 139 | for (var i = 0; i <= number; i++) { 140 | var w = input.value.indexOf("\n", position); 141 | if (w != -1 && w < start) { 142 | position = w + 1; 143 | minus++; 144 | } else { 145 | i = number; 146 | } 147 | } 148 | } 149 | start = start - minus; 150 | return { start: start, end: start, text: s.text, length: 0 }; 151 | } else if (typeof(input.selectionStart) == "number" ) { 152 | start = input.selectionStart; 153 | end = input.selectionEnd; 154 | part = input.value.substring(input.selectionStart, input.selectionEnd); 155 | return { start: start, end: end, text: part, length: end - start }; 156 | } else { return { start: undefined, end: undefined, text: undefined, length: undefined }; } 157 | }, 158 | 159 | // function for the replacement of the selected text 160 | replaceSelection: function(inputStr) { 161 | var input = this.jquery ? this[0] : this; 162 | //part for IE and Opera 163 | var start; 164 | var end; 165 | var position = 0; 166 | var rc; 167 | var re; 168 | var number = 0; 169 | var minus = 0; 170 | var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop; 171 | if (document.selection && typeof(input.selectionStart) != "number") { 172 | var s = document.selection.createRange(); 173 | 174 | // IE support 175 | if (typeof(input.selectionStart) != "number") { // return null if the selected text not from the needed area 176 | var firstRe; 177 | var secondRe; 178 | re = input.createTextRange(); 179 | rc = re.duplicate(); 180 | firstRe = re.text; 181 | re.moveToBookmark(s.getBookmark()); 182 | secondRe = re.text; 183 | rc.setEndPoint("EndToStart", re); 184 | if (firstRe == secondRe && firstRe != s.text) { 185 | return this; 186 | } 187 | } 188 | if (s.text) { 189 | part = s.text; 190 | if (input.value.match(/\n/g) != null) { 191 | number = input.value.match(/\n/g).length;// number of EOL simbols 192 | } 193 | // IE support 194 | start = rc.text.length; 195 | // remove all EOL to have the same start and end positons as in MOZILLA 196 | if (number > 0) { 197 | for (var i = 0; i <= number; i++) { 198 | var w = input.value.indexOf("\n", position); 199 | if (w != -1 && w < start) { 200 | position = w + 1; 201 | minus++; 202 | 203 | } else { 204 | i = number; 205 | } 206 | } 207 | } 208 | s.text = inputStr; 209 | caretPositionAmp = rc.text.length + inputStr.length; 210 | re.move("character", caretPositionAmp); 211 | document.selection.empty(); 212 | input.blur(); 213 | } 214 | return this; 215 | } else if (typeof(input.selectionStart) == "number" && // MOZILLA support 216 | input.selectionStart != input.selectionEnd) { 217 | 218 | start = input.selectionStart; 219 | end = input.selectionEnd; 220 | input.value = input.value.substr(0, start) + inputStr + input.value.substr(end); 221 | position = start + inputStr.length; 222 | input.setSelectionRange(position, position); 223 | input.scrollTop = mozScrollFix; 224 | return this; 225 | } 226 | return this; 227 | }, 228 | 229 | //Set Selection in text 230 | setSelection: function(startPosition, endPosition) { 231 | startPosition = parseInt(startPosition); 232 | endPosition = parseInt(endPosition); 233 | 234 | var input = this.jquery ? this[0] : this; 235 | input.focus (); 236 | if (typeof(input.selectionStart) != "number") { 237 | re = input.createTextRange(); 238 | if (re.text.length < endPosition) { 239 | endPosition = re.text.length+1; 240 | } 241 | } 242 | if (endPosition < startPosition) { 243 | return this; 244 | } 245 | if (document.selection) { 246 | var number = 0; 247 | var plus = 0; 248 | var position = 0; 249 | var plusEnd = 0; 250 | if (typeof(input.selectionStart) != "number") { // IE 251 | re.collapse(true); 252 | re.moveEnd('character', endPosition); 253 | re.moveStart('character', startPosition); 254 | re.select(); 255 | return this; 256 | } else if (typeof(input.selectionStart) == "number") { // Opera 257 | if (input.value.match(/\n/g) != null) { 258 | number = input.value.match(/\n/g).length;// number of EOL simbols 259 | } 260 | if (number > 0) { 261 | for (var i = 0; i <= number; i++) { 262 | var w = input.value.indexOf("\n", position); 263 | if (w != -1 && w < startPosition) { 264 | position = w + 1; 265 | plus++; 266 | plusEnd = plus; 267 | } else if (w != -1 && w >= startPosition && w <= endPosition) { 268 | if (w == startPosition + 1) { 269 | plus--; 270 | plusEnd--; 271 | position = w + 1; 272 | continue; 273 | } 274 | position = w + 1; 275 | plusEnd++; 276 | } else { 277 | i = number; 278 | } 279 | } 280 | } 281 | startPosition = startPosition +plus; 282 | endPosition = endPosition + plusEnd; 283 | input.selectionStart = startPosition; 284 | input.selectionEnd = endPosition; 285 | return this; 286 | } else { 287 | return this; 288 | } 289 | } 290 | else if (input.selectionStart) { // MOZILLA support 291 | input.focus (); 292 | input.selectionStart = startPosition; 293 | input.selectionEnd = endPosition; 294 | return this; 295 | } 296 | }, 297 | 298 | // insert text at current caret position 299 | insertAtCaretPos: function(inputStr) { 300 | var input = this.jquery ? this[0] : this; 301 | var start; 302 | var end; 303 | var position; 304 | var s; 305 | var re; 306 | var rc; 307 | var point; 308 | var minus = 0; 309 | var number = 0; 310 | var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop; 311 | input.focus(); 312 | if (document.selection && typeof(input.selectionStart) != "number") { 313 | if (input.value.match(/\n/g) != null) { 314 | number = input.value.match(/\n/g).length;// number of EOL simbols 315 | } 316 | point = parseInt(caretPositionAmp); 317 | if (number > 0) { 318 | for (var i = 0; i <= number; i++) { 319 | var w = input.value.indexOf("\n", position); 320 | if (w != -1 && w <= point) { 321 | position = w + 1; 322 | point = point - 1; 323 | minus++; 324 | } 325 | } 326 | } 327 | } 328 | caretPositionAmp = parseInt(caretPositionAmp); 329 | // IE 330 | input.onmouseup = function() { // for IE because it loses caret position when focus changed 331 | if (document.selection && typeof(input.selectionStart) != "number") { 332 | input.focus(); 333 | s = document.selection.createRange(); 334 | re = input.createTextRange(); 335 | rc = re.duplicate(); 336 | re.moveToBookmark(s.getBookmark()); 337 | rc.setEndPoint("EndToStart", re); 338 | caretPositionAmp = rc.text.length; 339 | } 340 | } 341 | 342 | if (document.selection && typeof(input.selectionStart) != "number") { 343 | s = document.selection.createRange(); 344 | if (s.text.length != 0) { 345 | return this; 346 | } 347 | re = input.createTextRange(); 348 | textLength = re.text.length; 349 | rc = re.duplicate(); 350 | re.moveToBookmark(s.getBookmark()); 351 | rc.setEndPoint("EndToStart", re); 352 | start = rc.text.length; 353 | if (caretPositionAmp > 0 && start ==0) { 354 | minus = caretPositionAmp - minus; 355 | re.move("character", minus); 356 | re.select(); 357 | s = document.selection.createRange(); 358 | caretPositionAmp += inputStr.length; 359 | } else if (!(caretPositionAmp >= 0) && textLength ==0) { 360 | s = document.selection.createRange(); 361 | caretPositionAmp = inputStr.length + textLength; 362 | } else if (!(caretPositionAmp >= 0) && start ==0) { 363 | re.move("character", textLength); 364 | re.select(); 365 | s = document.selection.createRange(); 366 | caretPositionAmp = inputStr.length + textLength; 367 | } else if (!(caretPositionAmp >= 0) && start > 0) { 368 | re.move("character", 0); 369 | document.selection.empty(); 370 | re.select(); 371 | s = document.selection.createRange(); 372 | caretPositionAmp = start + inputStr.length; 373 | } else if (caretPositionAmp >= 0 && caretPositionAmp == textLength) { 374 | if (textLength != 0) { 375 | re.move("character", textLength); 376 | re.select(); 377 | } else { 378 | re.move("character", 0); 379 | } 380 | s = document.selection.createRange(); 381 | caretPositionAmp = inputStr.length + textLength; 382 | } else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp >= start) { 383 | minus = caretPositionAmp - start; 384 | re.move("character", minus); 385 | document.selection.empty(); 386 | re.select(); 387 | s = document.selection.createRange(); 388 | caretPositionAmp = caretPositionAmp + inputStr.length; 389 | } else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp < start) { 390 | re.move("character", 0); 391 | document.selection.empty(); 392 | re.select(); 393 | s = document.selection.createRange(); 394 | caretPositionAmp = caretPositionAmp + inputStr.length; 395 | } else { 396 | document.selection.empty(); 397 | re.select(); 398 | s = document.selection.createRange(); 399 | caretPositionAmp = caretPositionAmp + inputStr.length; 400 | } 401 | s.text = inputStr; 402 | input.focus(); 403 | 404 | return this; 405 | } else if (typeof(input.selectionStart) == "number" && // MOZILLA support 406 | input.selectionStart == input.selectionEnd) { 407 | position = input.selectionStart + inputStr.length; 408 | start = input.selectionStart; 409 | end = input.selectionEnd; 410 | input.value = input.value.substr(0, start) + inputStr + input.value.substr(end); 411 | input.setSelectionRange(position, position); 412 | input.scrollTop = mozScrollFix; 413 | return this; 414 | } 415 | return this; 416 | }, 417 | 418 | 419 | // Set caret position 420 | setCaretPos: function(inputStr) { 421 | 422 | var input = this.jquery ? this[0] : this; 423 | var s; 424 | var re; 425 | var position; 426 | var number = 0; 427 | var minus = 0; 428 | var w; 429 | input.focus(); 430 | if (parseInt(inputStr) == 0) { 431 | return this; 432 | } 433 | //if (document.selection && typeof(input.selectionStart) == "number") { 434 | if (parseInt(inputStr) > 0) { 435 | inputStr = parseInt(inputStr) - 1; 436 | if (document.selection && typeof(input.selectionStart) == "number" && input.selectionStart == input.selectionEnd) { 437 | if (input.value.match(/\n/g) != null) { 438 | number = input.value.match(/\n/g).length;// number of EOL simbols 439 | } 440 | if (number > 0) { 441 | for (var i = 0; i <= number; i++) { 442 | w = input.value.indexOf("\n", position); 443 | if (w != -1 && w <= inputStr) { 444 | position = w + 1; 445 | inputStr = parseInt(inputStr) + 1; 446 | } 447 | } 448 | } 449 | } 450 | } 451 | else if (parseInt(inputStr) < 0) { 452 | inputStr = parseInt(inputStr) + 1; 453 | if (document.selection && typeof(input.selectionStart) != "number") { 454 | inputStr = input.value.length + parseInt(inputStr); 455 | if (input.value.match(/\n/g) != null) { 456 | number = input.value.match(/\n/g).length;// number of EOL simbols 457 | } 458 | if (number > 0) { 459 | for (var i = 0; i <= number; i++) { 460 | w = input.value.indexOf("\n", position); 461 | if (w != -1 && w <= inputStr) { 462 | position = w + 1; 463 | inputStr = parseInt(inputStr) - 1; 464 | minus += 1; 465 | } 466 | } 467 | inputStr = inputStr + minus - number; 468 | } 469 | } else if (document.selection && typeof(input.selectionStart) == "number") { 470 | inputStr = input.value.length + parseInt(inputStr); 471 | if (input.value.match(/\n/g) != null) { 472 | number = input.value.match(/\n/g).length;// number of EOL simbols 473 | } 474 | if (number > 0) { 475 | inputStr = parseInt(inputStr) - number; 476 | for (var i = 0; i <= number; i++) { 477 | w = input.value.indexOf("\n", position); 478 | if (w != -1 && w <= (inputStr)) { 479 | position = w + 1; 480 | inputStr = parseInt(inputStr) + 1; 481 | minus += 1; 482 | } 483 | } 484 | } 485 | } else { inputStr = input.value.length + parseInt(inputStr); } 486 | } else { return this; } 487 | // IE 488 | if (document.selection && typeof(input.selectionStart) != "number") { 489 | s = document.selection.createRange(); 490 | if (s.text != 0) { 491 | return this; 492 | } 493 | re = input.createTextRange(); 494 | re.collapse(true); 495 | re.moveEnd('character', inputStr); 496 | re.moveStart('character', inputStr); 497 | re.select(); 498 | caretPositionAmp = inputStr; 499 | 500 | return this; 501 | } else if (typeof(input.selectionStart) == "number" && // MOZILLA support 502 | input.selectionStart == input.selectionEnd) { 503 | input.setSelectionRange(inputStr, inputStr); 504 | return this; 505 | } 506 | return this; 507 | 508 | }, 509 | 510 | countCharacters: function(str) { 511 | var input = this.jquery ? this[0] : this; 512 | if (input.value.match(/\r/g) != null) { 513 | return input.value.length - input.value.match(/\r/g).length; 514 | } 515 | return input.value.length; 516 | }, 517 | 518 | setMaxLength: function(max, f) { 519 | this.each(function() { 520 | var input = this.jquery ? this[0] : this; 521 | var type = input.type; 522 | var isSelected; 523 | var maxCharacters; 524 | // remove limit if input is a negative number 525 | if (parseInt(max) < 0) { 526 | max=100000000; 527 | } 528 | if (type == "text") { 529 | input.maxLength = max; 530 | } 531 | if (type == "textarea" || type == "text") { 532 | input.onkeypress = function(e) { 533 | var spacesR = input.value.match(/\r/g); 534 | maxCharacters = max; 535 | if (spacesR != null) { 536 | maxCharacters = parseInt(maxCharacters) + spacesR.length; 537 | } 538 | // get event 539 | var key = e || event; 540 | var keyCode = key.keyCode; 541 | // check if any part of text is selected 542 | if (document.selection) { 543 | isSelected = document.selection.createRange().text.length > 0; 544 | } else { 545 | isSelected = input.selectionStart != input.selectionEnd; 546 | } 547 | if (input.value.length >= maxCharacters && (keyCode > 47 || keyCode == 32 || 548 | keyCode == 0 || keyCode == 13) && !key.ctrlKey && !key.altKey && !isSelected) { 549 | input.value = input.value.substring(0,maxCharacters); 550 | if (typeof(f) == "function") { f() } //callback function 551 | return false; 552 | } 553 | } 554 | input.onkeyup = function() { 555 | var spacesR = input.value.match(/\r/g); 556 | var plus = 0; 557 | var position = 0; 558 | maxCharacters = max; 559 | if (spacesR != null) { 560 | for (var i = 0; i <= spacesR.length; i++) { 561 | if (input.value.indexOf("\n", position) <= parseInt(max)) { 562 | plus++; 563 | position = input.value.indexOf("\n", position) + 1; 564 | } 565 | } 566 | maxCharacters = parseInt(max) + plus; 567 | } 568 | if (input.value.length > maxCharacters) { 569 | input.value = input.value.substring(0, maxCharacters); 570 | if (typeof(f) == "function") { f() } 571 | return this; 572 | } 573 | } 574 | } else { return this; } 575 | }) 576 | return this; 577 | } 578 | }); 579 | -------------------------------------------------------------------------------- /js/jquery.asuggest.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery textarea suggest plugin 3 | * 4 | * Copyright (c) 2009-2010 Roman Imankulov 5 | * 6 | * Dual licensed under the MIT and GPL licenses: 7 | * http://www.opensource.org/licenses/mit-license.php 8 | * http://www.gnu.org/licenses/gpl.html 9 | * 10 | * Requires: 11 | * - jQuery (tested with 1.3.x and 1.4.x) 12 | * - jquery.a-tools >= 1.4.1 (http://plugins.jquery.com/project/a-tools) 13 | */ 14 | 15 | /*globals jQuery,document */ 16 | 17 | (function ($) { 18 | // workaround for Opera browser 19 | if (navigator.userAgent.match(/opera/i)) { 20 | $(document).keypress(function (e) { 21 | if ($.asuggestFocused) { 22 | $.asuggestFocused.focus(); 23 | $.asuggestFocused = null; 24 | e.preventDefault(); 25 | e.stopPropagation(); 26 | } 27 | }); 28 | } 29 | 30 | $.asuggestKeys = { 31 | UNKNOWN: 0, 32 | SHIFT: 16, 33 | CTRL: 17, 34 | ALT: 18, 35 | LEFT: 37, 36 | UP: 38, 37 | RIGHT: 39, 38 | DOWN: 40, 39 | DEL: 46, 40 | TAB: 9, 41 | RETURN: 13, 42 | ESC: 27, 43 | COMMA: 188, 44 | PAGEUP: 33, 45 | PAGEDOWN: 34, 46 | BACKSPACE: 8, 47 | SPACE: 32 48 | }; 49 | $.asuggestFocused = null; 50 | 51 | $.fn.asuggest = function (suggests, options) { 52 | return this.each(function () { 53 | $.makeSuggest(this, suggests, options); 54 | }); 55 | }; 56 | 57 | $.fn.asuggest.defaults = { 58 | 'delimiters': '\n ', 59 | 'minChunkSize': 1, 60 | 'cycleOnTab': true, 61 | 'autoComplete': true, 62 | 'endingSymbols': ' ', 63 | 'stopSuggestionKeys': [$.asuggestKeys.RETURN, $.asuggestKeys.SPACE], 64 | 'ignoreCase': false 65 | }; 66 | 67 | /* Make suggest: 68 | * 69 | * create and return jQuery object on the top of DOM object 70 | * and store suggests as part of this object 71 | * 72 | * @param area: HTML DOM element to add suggests to 73 | * @param suggests: The array of suggest strings 74 | * @param options: The options object 75 | */ 76 | $.makeSuggest = function (area, suggests, options) { 77 | options = $.extend({}, $.fn.asuggest.defaults, options); 78 | 79 | var KEY = $.asuggestKeys, 80 | $area = $(area); 81 | $area.suggests = suggests; 82 | $area.options = options; 83 | 84 | /* Internal method: get the chunk of text before the cursor */ 85 | $area.getChunk = function () { 86 | var delimiters = this.options.delimiters.split(''), // array of chars 87 | textBeforeCursor = this.val().substr(0, this.getSelection().start), 88 | indexOfDelimiter = -1, 89 | i, 90 | d, 91 | idx; 92 | for (i = 0; i < delimiters.length; i++) { 93 | d = delimiters[i]; 94 | idx = textBeforeCursor.lastIndexOf(d); 95 | if (idx > indexOfDelimiter) { 96 | indexOfDelimiter = idx; 97 | } 98 | } 99 | if (indexOfDelimiter < 0) { 100 | return textBeforeCursor; 101 | } else { 102 | return textBeforeCursor.substr(indexOfDelimiter + 1); 103 | } 104 | }; 105 | 106 | /* Internal method: get completion. 107 | * If performCycle is true then analyze getChunk() and and getSelection() 108 | */ 109 | $area.getCompletion = function (performCycle) { 110 | var text = this.getChunk(), 111 | selectionText = this.getSelection().text, 112 | suggests = this.suggests, 113 | foundAlreadySelectedValue = false, 114 | firstMatchedValue = null, 115 | i, 116 | suggest; 117 | // search the variant 118 | for (i = 0; i < suggests.length; i++) { 119 | suggest = suggests[i]; 120 | if ($area.options.ignoreCase) { 121 | suggest = suggest.toLowerCase(); 122 | text = text.toLowerCase(); 123 | } 124 | // some variant is found 125 | if (suggest.indexOf(text) === 0) { 126 | if (performCycle) { 127 | if (text + selectionText === suggest) { 128 | foundAlreadySelectedValue = true; 129 | } else if (foundAlreadySelectedValue) { 130 | return suggest.substr(text.length); 131 | } else if (firstMatchedValue === null) { 132 | firstMatchedValue = suggest; 133 | } 134 | } else { 135 | return suggest.substr(text.length); 136 | } 137 | } 138 | } 139 | if (performCycle && firstMatchedValue) { 140 | return firstMatchedValue.substr(text.length); 141 | } else { 142 | return null; 143 | } 144 | }; 145 | 146 | $area.updateSelection = function (completion) { 147 | if (completion) { 148 | var _selectionStart = $area.getSelection().start, 149 | _selectionEnd = _selectionStart + completion.length; 150 | if ($area.getSelection().text === "") { 151 | if ($area.val().length === _selectionStart) { // Weird IE workaround, I really have no idea why it works 152 | $area.setCaretPos(_selectionStart + 10000); 153 | } 154 | $area.insertAtCaretPos(completion); 155 | } else { 156 | $area.replaceSelection(completion); 157 | } 158 | $area.setSelection(_selectionStart, _selectionEnd); 159 | } 160 | }; 161 | 162 | $area.unbind('keydown.asuggest').bind('keydown.asuggest', function (e) { 163 | if (e.keyCode === KEY.TAB) { 164 | if ($area.options.cycleOnTab) { 165 | var chunk = $area.getChunk(); 166 | if (chunk.length >= $area.options.minChunkSize) { 167 | $area.updateSelection($area.getCompletion(true)); 168 | } 169 | e.preventDefault(); 170 | e.stopPropagation(); 171 | $area.focus(); 172 | $.asuggestFocused = this; 173 | return false; 174 | } 175 | } 176 | // Check for conditions to stop suggestion 177 | if ($area.getSelection().length && 178 | $.inArray(e.keyCode, $area.options.stopSuggestionKeys) !== -1) { 179 | // apply suggestion. Clean up selection and insert a space 180 | var _selectionEnd = $area.getSelection().end + 181 | $area.options.endingSymbols.length; 182 | var _text = $area.getSelection().text + 183 | $area.options.endingSymbols; 184 | $area.replaceSelection(_text); 185 | $area.setSelection(_selectionEnd, _selectionEnd); 186 | e.preventDefault(); 187 | e.stopPropagation(); 188 | this.focus(); 189 | $.asuggestFocused = this; 190 | return false; 191 | } 192 | }); 193 | 194 | $area.unbind('keyup.asuggest').bind('keyup.asuggest', function (e) { 195 | var hasSpecialKeys = e.altKey || e.metaKey || e.ctrlKey, 196 | hasSpecialKeysOrShift = hasSpecialKeys || e.shiftKey; 197 | switch (e.keyCode) { 198 | case KEY.UNKNOWN: // Special key released 199 | case KEY.SHIFT: 200 | case KEY.CTRL: 201 | case KEY.ALT: 202 | case KEY.RETURN: // we don't want to suggest when RETURN key has pressed (another IE workaround) 203 | break; 204 | case KEY.TAB: 205 | if (!hasSpecialKeysOrShift && $area.options.cycleOnTab) { 206 | break; 207 | } 208 | case KEY.ESC: 209 | case KEY.BACKSPACE: 210 | case KEY.DEL: 211 | case KEY.UP: 212 | case KEY.DOWN: 213 | case KEY.LEFT: 214 | case KEY.RIGHT: 215 | if (!hasSpecialKeysOrShift && $area.options.autoComplete) { 216 | $area.replaceSelection(""); 217 | } 218 | break; 219 | default: 220 | if (!hasSpecialKeys && $area.options.autoComplete) { 221 | var chunk = $area.getChunk(); 222 | if (chunk.length >= $area.options.minChunkSize) { 223 | $area.updateSelection($area.getCompletion(false)); 224 | } 225 | } 226 | break; 227 | } 228 | }); 229 | return $area; 230 | }; 231 | }(jQuery)); 232 | -------------------------------------------------------------------------------- /js/jquery.sticky.js: -------------------------------------------------------------------------------- 1 | // Sticky Plugin v1.0.0 for jQuery 2 | // ============= 3 | // Author: Anthony Garand 4 | // Improvements by German M. Bravo (Kronuz) and Ruud Kamphuis (ruudk) 5 | // Improvements by Leonardo C. Daronco (daronco) 6 | // Created: 2/14/2011 7 | // Date: 2/12/2012 8 | // Website: http://labs.anthonygarand.com/sticky 9 | // Description: Makes an element on the page stick on the screen as you scroll 10 | // It will only set the 'top' and 'position' of your element, you 11 | // might need to adjust the width in some cases. 12 | 13 | (function($) { 14 | var defaults = { 15 | topSpacing: 0, 16 | bottomSpacing: 0, 17 | className: 'is-sticky', 18 | wrapperClassName: 'sticky-wrapper', 19 | center: false, 20 | getWidthFrom: '' 21 | }, 22 | $window = $(window), 23 | $document = $(document), 24 | sticked = [], 25 | windowHeight = $window.height(), 26 | scroller = function() { 27 | var scrollTop = $window.scrollTop(), 28 | documentHeight = $document.height(), 29 | dwh = documentHeight - windowHeight, 30 | extra = (scrollTop > dwh) ? dwh - scrollTop : 0; 31 | 32 | for (var i = 0; i < sticked.length; i++) { 33 | var s = sticked[i], 34 | elementTop = s.stickyWrapper.offset().top, 35 | etse = elementTop - s.topSpacing - extra; 36 | 37 | if (scrollTop <= etse) { 38 | if (s.currentTop !== null) { 39 | s.stickyElement 40 | .css('position', '') 41 | .css('top', ''); 42 | s.stickyElement.parent().removeClass(s.className); 43 | s.currentTop = null; 44 | } 45 | } 46 | else { 47 | var newTop = documentHeight - s.stickyElement.outerHeight() 48 | - s.topSpacing - s.bottomSpacing - scrollTop - extra; 49 | if (newTop < 0) { 50 | newTop = newTop + s.topSpacing; 51 | } else { 52 | newTop = s.topSpacing; 53 | } 54 | if (s.currentTop != newTop) { 55 | s.stickyElement 56 | .css('position', 'fixed') 57 | .css('top', newTop); 58 | 59 | if (typeof s.getWidthFrom !== 'undefined') { 60 | s.stickyElement.css('width', $(s.getWidthFrom).width()); 61 | } 62 | 63 | s.stickyElement.parent().addClass(s.className); 64 | s.currentTop = newTop; 65 | } 66 | } 67 | } 68 | }, 69 | resizer = function() { 70 | windowHeight = $window.height(); 71 | }, 72 | methods = { 73 | init: function(options) { 74 | var o = $.extend(defaults, options); 75 | return this.each(function() { 76 | var stickyElement = $(this); 77 | 78 | var stickyId = stickyElement.attr('id'); 79 | var wrapper = $('
') 80 | .attr('id', stickyId + '-sticky-wrapper') 81 | .addClass(o.wrapperClassName); 82 | stickyElement.wrapAll(wrapper); 83 | 84 | if (o.center) { 85 | stickyElement.parent().css({width:stickyElement.outerWidth(),marginLeft:"auto",marginRight:"auto"}); 86 | } 87 | 88 | if (stickyElement.css("float") == "right") { 89 | stickyElement.css({"float":"none"}).parent().css({"float":"right"}); 90 | } 91 | 92 | var stickyWrapper = stickyElement.parent(); 93 | stickyWrapper.css('height', stickyElement.outerHeight()); 94 | sticked.push({ 95 | topSpacing: o.topSpacing, 96 | bottomSpacing: o.bottomSpacing, 97 | stickyElement: stickyElement, 98 | currentTop: null, 99 | stickyWrapper: stickyWrapper, 100 | className: o.className, 101 | getWidthFrom: o.getWidthFrom 102 | }); 103 | }); 104 | }, 105 | update: scroller, 106 | unstick: function(options) { 107 | return this.each(function() { 108 | var unstickyElement = $(this); 109 | 110 | removeIdx = -1; 111 | for (var i = 0; i < sticked.length; i++) 112 | { 113 | if (sticked[i].stickyElement.get(0) == unstickyElement.get(0)) 114 | { 115 | removeIdx = i; 116 | } 117 | } 118 | if(removeIdx != -1) 119 | { 120 | sticked.splice(removeIdx,1); 121 | unstickyElement.unwrap(); 122 | unstickyElement.removeAttr('style'); 123 | } 124 | }); 125 | } 126 | }; 127 | 128 | // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer): 129 | if (window.addEventListener) { 130 | window.addEventListener('scroll', scroller, false); 131 | window.addEventListener('resize', resizer, false); 132 | } else if (window.attachEvent) { 133 | window.attachEvent('onscroll', scroller); 134 | window.attachEvent('onresize', resizer); 135 | } 136 | 137 | $.fn.sticky = function(method) { 138 | if (methods[method]) { 139 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 140 | } else if (typeof method === 'object' || !method ) { 141 | return methods.init.apply( this, arguments ); 142 | } else { 143 | $.error('Method ' + method + ' does not exist on jQuery.sticky'); 144 | } 145 | }; 146 | 147 | $.fn.unstick = function(method) { 148 | if (methods[method]) { 149 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 150 | } else if (typeof method === 'object' || !method ) { 151 | return methods.unstick.apply( this, arguments ); 152 | } else { 153 | $.error('Method ' + method + ' does not exist on jQuery.sticky'); 154 | } 155 | 156 | }; 157 | $(function() { 158 | setTimeout(scroller, 0); 159 | }); 160 | })(jQuery); 161 | -------------------------------------------------------------------------------- /js/jquery.tooltipster.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Tooltipster 3.2.2 | 2014-04-07 4 | A rockin' custom tooltip jQuery plugin 5 | 6 | Developed by Caleb Jacob under the MIT license http://opensource.org/licenses/MIT 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | 10 | */ 11 | 12 | ;(function ($, window, document) { 13 | 14 | var pluginName = "tooltipster", 15 | defaults = { 16 | animation: 'fade', 17 | arrow: true, 18 | arrowColor: '', 19 | autoClose: true, 20 | content: null, 21 | contentAsHTML: false, 22 | contentCloning: true, 23 | delay: 200, 24 | fixedWidth: 0, 25 | maxWidth: 0, 26 | functionInit: function(origin, content) {}, 27 | functionBefore: function(origin, continueTooltip) { 28 | continueTooltip(); 29 | }, 30 | functionReady: function(origin, tooltip) {}, 31 | functionAfter: function(origin) {}, 32 | icon: '(?)', 33 | iconCloning: true, 34 | iconDesktop: false, 35 | iconTouch: false, 36 | iconTheme: 'tooltipster-icon', 37 | interactive: false, 38 | interactiveTolerance: 350, 39 | multiple: false, 40 | offsetX: 0, 41 | offsetY: 0, 42 | onlyOne: false, 43 | position: 'top', 44 | positionTracker: false, 45 | speed: 350, 46 | timer: 0, 47 | theme: 'tooltipster-default', 48 | touchDevices: true, 49 | trigger: 'hover', 50 | updateAnimation: true 51 | }; 52 | 53 | function Plugin(element, options) { 54 | 55 | // list of instance variables 56 | 57 | this.bodyOverflowX; 58 | // stack of custom callbacks provided as parameters to API methods 59 | this.callbacks = { 60 | hide: [], 61 | show: [] 62 | }; 63 | this.checkInterval = null; 64 | // this will be the user content shown in the tooltip. A capital "C" is used because there is also a method called content() 65 | this.Content; 66 | // this is the original element which is being applied the tooltipster plugin 67 | this.$el = $(element); 68 | // this will be the element which triggers the appearance of the tooltip on hover/click/custom events. 69 | // it will be the same as this.$el if icons are not used (see in the options), otherwise it will correspond to the created icon 70 | this.$elProxy; 71 | this.elProxyPosition; 72 | this.enabled = true; 73 | this.options = $.extend({}, defaults, options); 74 | this.mouseIsOverProxy = false; 75 | // a unique namespace per instance, for easy selective unbinding 76 | this.namespace = 'tooltipster-'+ Math.round(Math.random()*100000); 77 | // Status (capital S) can be either : appearing, shown, disappearing, hidden 78 | this.Status = 'hidden'; 79 | this.timerHide = null; 80 | this.timerShow = null; 81 | // this will be the tooltip element (jQuery wrapped HTML element) 82 | this.$tooltip; 83 | 84 | // for backward compatibility 85 | this.options.iconTheme = this.options.iconTheme.replace('.', ''); 86 | this.options.theme = this.options.theme.replace('.', ''); 87 | 88 | // launch 89 | 90 | this._init(); 91 | } 92 | 93 | Plugin.prototype = { 94 | 95 | _init: function() { 96 | 97 | var self = this; 98 | 99 | // disable the plugin on old browsers (including IE7 and lower) 100 | if (document.querySelector) { 101 | 102 | // note : the content is null (empty) by default and can stay that way if the plugin remains initialized but not fed any content. The tooltip will just not appear. 103 | 104 | // if content is provided in the options, its has precedence over the title attribute. Remark : an empty string is considered content, only 'null' represents the absence of content. 105 | if (self.options.content !== null){ 106 | self._content_set(self.options.content); 107 | } 108 | else { 109 | // the same remark as above applies : empty strings (like title="") are considered content and will be shown. Do not define any attribute at all if you want to initialize the plugin without content at start. 110 | var t = self.$el.attr('title'); 111 | if(typeof t === 'undefined') t = null; 112 | 113 | self._content_set(t); 114 | } 115 | 116 | var c = self.options.functionInit.call(self.$el, self.$el, self.Content); 117 | if(typeof c !== 'undefined') self._content_set(c); 118 | 119 | self.$el 120 | // strip the title off of the element to prevent the default tooltips from popping up 121 | .removeAttr('title') 122 | // to be able to find all instances on the page later (upon window events in particular) 123 | .addClass('tooltipstered'); 124 | 125 | // detect if we're changing the tooltip origin to an icon 126 | // note about this condition : if the device has touch capability and self.options.iconTouch is false, you'll have no icons event though you may consider your device as a desktop if it also has a mouse. Not sure why someone would have this use case though. 127 | if ((!deviceHasTouchCapability && self.options.iconDesktop) || (deviceHasTouchCapability && self.options.iconTouch)) { 128 | 129 | // TODO : the tooltip should be automatically be given an absolute position to be near the origin. Otherwise, when the origin is floating or what, it's going to be nowhere near it and disturb the position flow of the page elements. It will imply that the icon also detects when its origin moves, to follow it : not trivial. 130 | // Until it's done, the icon feature does not really make sense since the user still has most of the work to do by himself 131 | 132 | // if the icon provided is in the form of a string 133 | if(typeof self.options.icon === 'string'){ 134 | // wrap it in a span with the icon class 135 | self.$elProxy = $(''); 136 | self.$elProxy.text(self.options.icon); 137 | } 138 | // if it is an object (sensible choice) 139 | else { 140 | // (deep) clone the object if iconCloning == true, to make sure every instance has its own proxy. We use the icon without wrapping, no need to. We do not give it a class either, as the user will undoubtedly style the object on his own and since our css properties may conflict with his own 141 | if (self.options.iconCloning) self.$elProxy = self.options.icon.clone(true); 142 | else self.$elProxy = self.options.icon; 143 | } 144 | 145 | self.$elProxy.insertAfter(self.$el); 146 | } 147 | else { 148 | self.$elProxy = self.$el; 149 | } 150 | 151 | // for 'click' and 'hover' triggers : bind on events to open the tooltip. Closing is now handled in _showNow() because of its bindings. 152 | // Notes about touch events : 153 | // - mouseenter, mouseleave and clicks happen even on pure touch devices because they are emulated. deviceIsPureTouch() is a simple attempt to detect them. 154 | // - on hybrid devices, we do not prevent touch gesture from opening tooltips. It would be too complex to differentiate real mouse events from emulated ones. 155 | // - we check deviceIsPureTouch() at each event rather than prior to binding because the situation may change during browsing 156 | if (self.options.trigger == 'hover') { 157 | 158 | // these binding are for mouse interaction only 159 | self.$elProxy 160 | .on('mouseenter.'+ self.namespace, function() { 161 | if (!deviceIsPureTouch() || self.options.touchDevices) { 162 | self.mouseIsOverProxy = true; 163 | self._show(); 164 | } 165 | }) 166 | .on('mouseleave.'+ self.namespace, function() { 167 | if (!deviceIsPureTouch() || self.options.touchDevices) { 168 | self.mouseIsOverProxy = false; 169 | } 170 | }); 171 | 172 | // for touch interaction only 173 | if (deviceHasTouchCapability && self.options.touchDevices) { 174 | 175 | // for touch devices, we immediately display the tooltip because we cannot rely on mouseleave to handle the delay 176 | self.$elProxy.on('touchstart.'+ self.namespace, function() { 177 | self._showNow(); 178 | }); 179 | } 180 | } 181 | else if (self.options.trigger == 'click') { 182 | 183 | // note : for touch devices, we do not bind on touchstart, we only rely on the emulated clicks (triggered by taps) 184 | self.$elProxy.on('click.'+ self.namespace, function() { 185 | if (!deviceIsPureTouch() || self.options.touchDevices) { 186 | self._show(); 187 | } 188 | }); 189 | } 190 | } 191 | }, 192 | 193 | // this function will schedule the opening of the tooltip after the delay, if there is one 194 | _show: function() { 195 | 196 | var self = this; 197 | 198 | if (self.Status != 'shown' && self.Status != 'appearing') { 199 | 200 | if (self.options.delay) { 201 | self.timerShow = setTimeout(function(){ 202 | 203 | // for hover trigger, we check if the mouse is still over the proxy, otherwise we do not show anything 204 | if (self.options.trigger == 'click' || (self.options.trigger == 'hover' && self.mouseIsOverProxy)) { 205 | self._showNow(); 206 | } 207 | }, self.options.delay); 208 | } 209 | else self._showNow(); 210 | } 211 | }, 212 | 213 | // this function will open the tooltip right away 214 | _showNow: function(callback) { 215 | 216 | var self = this; 217 | 218 | // call our constructor custom function before continuing 219 | self.options.functionBefore.call(self.$el, self.$el, function() { 220 | 221 | // continue only if the tooltip is enabled and has any content 222 | if (self.enabled && self.Content !== null) { 223 | 224 | // save the method callback and cancel hide method callbacks 225 | if (callback) self.callbacks.show.push(callback); 226 | self.callbacks.hide = []; 227 | 228 | //get rid of any appearance timer 229 | clearTimeout(self.timerShow); 230 | self.timerShow = null; 231 | clearTimeout(self.timerHide); 232 | self.timerHide = null; 233 | 234 | // if we only want one tooltip open at a time, close all auto-closing tooltips currently open and not already disappearing 235 | if (self.options.onlyOne) { 236 | $('.tooltipstered').not(self.$el).each(function(i,el) { 237 | 238 | var $el = $(el), 239 | nss = $el.data('tooltipster-ns'); 240 | 241 | // iterate on all tooltips of the element 242 | $.each(nss, function(i, ns){ 243 | var instance = $el.data(ns), 244 | // we have to use the public methods here 245 | s = instance.status(), 246 | ac = instance.option('autoClose'); 247 | 248 | if (s !== 'hidden' && s !== 'disappearing' && ac) { 249 | instance.hide(); 250 | } 251 | }); 252 | }); 253 | } 254 | 255 | var finish = function() { 256 | self.Status = 'shown'; 257 | 258 | // trigger any show method custom callbacks and reset them 259 | $.each(self.callbacks.show, function(i,c) { c.call(self.$el); }); 260 | self.callbacks.show = []; 261 | }; 262 | 263 | // if this origin already has its tooltip open 264 | if (self.Status !== 'hidden') { 265 | 266 | // the timer (if any) will start (or restart) right now 267 | var extraTime = 0; 268 | 269 | // if it was disappearing, cancel that 270 | if (self.Status === 'disappearing') { 271 | 272 | self.Status = 'appearing'; 273 | 274 | if (supportsTransitions()) { 275 | 276 | self.$tooltip 277 | .clearQueue() 278 | .removeClass('tooltipster-dying') 279 | .addClass('tooltipster-'+ self.options.animation +'-show'); 280 | 281 | if (self.options.speed > 0) self.$tooltip.delay(self.options.speed); 282 | 283 | self.$tooltip.queue(finish); 284 | } 285 | else { 286 | // in case the tooltip was currently fading out, bring it back to life 287 | self.$tooltip 288 | .stop() 289 | .fadeIn(finish); 290 | } 291 | } 292 | // if the tooltip is already open, we still need to trigger the method custom callback 293 | else if(self.Status === 'shown') { 294 | finish(); 295 | } 296 | } 297 | // if the tooltip isn't already open, open that sucker up! 298 | else { 299 | 300 | self.Status = 'appearing'; 301 | 302 | // the timer (if any) will start when the tooltip has fully appeared after its transition 303 | var extraTime = self.options.speed; 304 | 305 | // disable horizontal scrollbar to keep overflowing tooltips from jacking with it and then restore it to its previous value 306 | self.bodyOverflowX = $('body').css('overflow-x'); 307 | $('body').css('overflow-x', 'hidden'); 308 | 309 | // get some other settings related to building the tooltip 310 | var animation = 'tooltipster-' + self.options.animation, 311 | animationSpeed = '-webkit-transition-duration: '+ self.options.speed +'ms; -webkit-animation-duration: '+ self.options.speed +'ms; -moz-transition-duration: '+ self.options.speed +'ms; -moz-animation-duration: '+ self.options.speed +'ms; -o-transition-duration: '+ self.options.speed +'ms; -o-animation-duration: '+ self.options.speed +'ms; -ms-transition-duration: '+ self.options.speed +'ms; -ms-animation-duration: '+ self.options.speed +'ms; transition-duration: '+ self.options.speed +'ms; animation-duration: '+ self.options.speed +'ms;', 312 | fixedWidth = self.options.fixedWidth > 0 ? 'width:'+ Math.round(self.options.fixedWidth) +'px;' : '', 313 | maxWidth = self.options.maxWidth > 0 ? 'max-width:'+ Math.round(self.options.maxWidth) +'px;' : '', 314 | pointerEvents = self.options.interactive ? 'pointer-events: auto;' : ''; 315 | 316 | // build the base of our tooltip 317 | self.$tooltip = $('
'); 318 | 319 | // only add the animation class if the user has a browser that supports animations 320 | if (supportsTransitions()) self.$tooltip.addClass(animation); 321 | 322 | // insert the content 323 | self._content_insert(); 324 | 325 | // attach 326 | self.$tooltip.appendTo('body'); 327 | 328 | // do all the crazy calculations and positioning 329 | self.reposition(); 330 | 331 | // call our custom callback since the content of the tooltip is now part of the DOM 332 | self.options.functionReady.call(self.$el, self.$el, self.$tooltip); 333 | 334 | // animate in the tooltip 335 | if (supportsTransitions()) { 336 | 337 | self.$tooltip.addClass(animation + '-show'); 338 | 339 | if(self.options.speed > 0) self.$tooltip.delay(self.options.speed); 340 | 341 | self.$tooltip.queue(finish); 342 | } 343 | else { 344 | self.$tooltip.css('display', 'none').fadeIn(self.options.speed, finish); 345 | } 346 | 347 | // will check if our tooltip origin is removed while the tooltip is shown 348 | self._interval_set(); 349 | 350 | // reposition on scroll (otherwise position:fixed element's tooltips will move away form their origin) and on resize (in case position can/has to be changed) 351 | $(window).on('scroll.'+ self.namespace +' resize.'+ self.namespace, function() { 352 | self.reposition(); 353 | }); 354 | 355 | // auto-close bindings 356 | if (self.options.autoClose) { 357 | 358 | // in case a listener is already bound for autoclosing (mouse or touch, hover or click), unbind it first 359 | $('body').off('.'+ self.namespace); 360 | 361 | // here we'll have to set different sets of bindings for both touch and mouse 362 | if (self.options.trigger == 'hover') { 363 | 364 | // if the user touches the body, hide 365 | if (deviceHasTouchCapability) { 366 | // timeout 0 : explanation below in click section 367 | setTimeout(function() { 368 | // we don't want to bind on click here because the initial touchstart event has not yet triggered its click event, which is thus about to happen 369 | $('body').on('touchstart.'+ self.namespace, function() { 370 | self.hide(); 371 | }); 372 | }, 0); 373 | } 374 | 375 | // if we have to allow interaction 376 | if (self.options.interactive) { 377 | 378 | // touch events inside the tooltip must not close it 379 | if (deviceHasTouchCapability) { 380 | self.$tooltip.on('touchstart.'+ self.namespace, function(event) { 381 | event.stopPropagation(); 382 | }); 383 | } 384 | 385 | // as for mouse interaction, we get rid of the tooltip only after the mouse has spent some time out of it 386 | var tolerance = null; 387 | 388 | self.$elProxy.add(self.$tooltip) 389 | // hide after some time out of the proxy and the tooltip 390 | .on('mouseleave.'+ self.namespace + '-autoClose', function() { 391 | clearTimeout(tolerance); 392 | tolerance = setTimeout(function(){ 393 | self.hide(); 394 | }, self.options.interactiveTolerance); 395 | }) 396 | // suspend timeout when the mouse is over the proxy or the tooltip 397 | .on('mouseenter.'+ self.namespace + '-autoClose', function() { 398 | clearTimeout(tolerance); 399 | }); 400 | } 401 | // if this is a non-interactive tooltip, get rid of it if the mouse leaves 402 | else { 403 | self.$elProxy.on('mouseleave.'+ self.namespace + '-autoClose', function() { 404 | self.hide(); 405 | }); 406 | } 407 | } 408 | // here we'll set the same bindings for both clicks and touch on the body to hide the tooltip 409 | else if(self.options.trigger == 'click'){ 410 | 411 | // use a timeout to prevent immediate closing if the method was called on a click event and if options.delay == 0 (because of bubbling) 412 | setTimeout(function() { 413 | $('body').on('click.'+ self.namespace +' touchstart.'+ self.namespace, function() { 414 | self.hide(); 415 | }); 416 | }, 0); 417 | 418 | // if interactive, we'll stop the events that were emitted from inside the tooltip to stop autoClosing 419 | if (self.options.interactive) { 420 | 421 | // note : the touch events will just not be used if the plugin is not enabled on touch devices 422 | self.$tooltip.on('click.'+ self.namespace +' touchstart.'+ self.namespace, function(event) { 423 | event.stopPropagation(); 424 | }); 425 | } 426 | } 427 | } 428 | } 429 | 430 | // if we have a timer set, let the countdown begin 431 | if (self.options.timer > 0) { 432 | 433 | self.timerHide = setTimeout(function() { 434 | self.timerHide = null; 435 | self.hide(); 436 | }, self.options.timer + extraTime); 437 | } 438 | } 439 | }); 440 | }, 441 | 442 | _interval_set: function() { 443 | 444 | var self = this; 445 | 446 | self.checkInterval = setInterval(function() { 447 | 448 | // if the tooltip and/or its interval should be stopped 449 | if ( 450 | // if the origin has been removed 451 | $('body').find(self.$el).length === 0 452 | // if the elProxy has been removed 453 | || $('body').find(self.$elProxy).length === 0 454 | // if the tooltip has been closed 455 | || self.Status == 'hidden' 456 | // if the tooltip has somehow been removed 457 | || $('body').find(self.$tooltip).length === 0 458 | ) { 459 | // remove the tooltip if it's still here 460 | if (self.Status == 'shown' || self.Status == 'appearing') self.hide(); 461 | 462 | // clear this interval as it is no longer necessary 463 | self._interval_cancel(); 464 | } 465 | // if everything is alright 466 | else { 467 | // compare the former and current positions of the elProxy to reposition the tooltip if need be 468 | if(self.options.positionTracker){ 469 | 470 | var p = self._repositionInfo(self.$elProxy), 471 | identical = false; 472 | 473 | // compare size first (a change requires repositioning too) 474 | if(areEqual(p.dimension, self.elProxyPosition.dimension)){ 475 | 476 | // for elements with a fixed position, we track the top and left properties (relative to window) 477 | if(self.$elProxy.css('position') === 'fixed'){ 478 | if(areEqual(p.position, self.elProxyPosition.position)) identical = true; 479 | } 480 | // otherwise, track total offset (relative to document) 481 | else { 482 | if(areEqual(p.offset, self.elProxyPosition.offset)) identical = true; 483 | } 484 | } 485 | 486 | if(!identical){ 487 | self.reposition(); 488 | } 489 | } 490 | } 491 | }, 200); 492 | }, 493 | 494 | _interval_cancel: function() { 495 | clearInterval(this.checkInterval); 496 | // clean delete 497 | this.checkInterval = null; 498 | }, 499 | 500 | _content_set: function(content) { 501 | // clone if asked. Cloning the object makes sure that each instance has its own version of the content (in case a same object were provided for several instances) 502 | // reminder : typeof null === object 503 | if (typeof content === 'object' && content !== null && this.options.contentCloning) { 504 | content = content.clone(true); 505 | } 506 | this.Content = content; 507 | }, 508 | 509 | _content_insert: function() { 510 | 511 | var self = this, 512 | $d = this.$tooltip.find('.tooltipster-content'); 513 | 514 | if (typeof self.Content === 'string' && !self.options.contentAsHTML) { 515 | $d.text(self.Content); 516 | } 517 | else { 518 | $d 519 | .empty() 520 | .append(self.Content); 521 | } 522 | }, 523 | 524 | _update: function(content) { 525 | 526 | var self = this; 527 | 528 | // change the content 529 | self._content_set(content); 530 | 531 | if (self.Content !== null) { 532 | 533 | // update the tooltip if it is open 534 | if (self.Status !== 'hidden') { 535 | 536 | // reset the content in the tooltip 537 | self._content_insert(); 538 | 539 | // reposition and resize the tooltip 540 | self.reposition(); 541 | 542 | // if we want to play a little animation showing the content changed 543 | if (self.options.updateAnimation) { 544 | 545 | if (supportsTransitions()) { 546 | 547 | self.$tooltip.css({ 548 | 'width': '', 549 | '-webkit-transition': 'all ' + self.options.speed + 'ms, width 0ms, height 0ms, left 0ms, top 0ms', 550 | '-moz-transition': 'all ' + self.options.speed + 'ms, width 0ms, height 0ms, left 0ms, top 0ms', 551 | '-o-transition': 'all ' + self.options.speed + 'ms, width 0ms, height 0ms, left 0ms, top 0ms', 552 | '-ms-transition': 'all ' + self.options.speed + 'ms, width 0ms, height 0ms, left 0ms, top 0ms', 553 | 'transition': 'all ' + self.options.speed + 'ms, width 0ms, height 0ms, left 0ms, top 0ms' 554 | }).addClass('tooltipster-content-changing'); 555 | 556 | // reset the CSS transitions and finish the change animation 557 | setTimeout(function() { 558 | 559 | if(self.Status != 'hidden'){ 560 | 561 | self.$tooltip.removeClass('tooltipster-content-changing'); 562 | 563 | // after the changing animation has completed, reset the CSS transitions 564 | setTimeout(function() { 565 | 566 | if(self.Status !== 'hidden'){ 567 | self.$tooltip.css({ 568 | '-webkit-transition': self.options.speed + 'ms', 569 | '-moz-transition': self.options.speed + 'ms', 570 | '-o-transition': self.options.speed + 'ms', 571 | '-ms-transition': self.options.speed + 'ms', 572 | 'transition': self.options.speed + 'ms' 573 | }); 574 | } 575 | }, self.options.speed); 576 | } 577 | }, self.options.speed); 578 | } 579 | else { 580 | self.$tooltip.fadeTo(self.options.speed, 0.5, function() { 581 | if(self.Status != 'hidden'){ 582 | self.$tooltip.fadeTo(self.options.speed, 1); 583 | } 584 | }); 585 | } 586 | } 587 | } 588 | } 589 | else { 590 | self.hide(); 591 | } 592 | }, 593 | 594 | _repositionInfo: function($el) { 595 | return { 596 | dimension: { 597 | height: $el.outerHeight(false), 598 | width: $el.outerWidth(false) 599 | }, 600 | offset: $el.offset(), 601 | position: { 602 | left: parseInt($el.css('left')), 603 | top: parseInt($el.css('top')) 604 | } 605 | }; 606 | }, 607 | 608 | hide: function(callback) { 609 | 610 | var self = this; 611 | 612 | // save the method custom callback and cancel any show method custom callbacks 613 | if (callback) self.callbacks.hide.push(callback); 614 | self.callbacks.show = []; 615 | 616 | // get rid of any appearance timeout 617 | clearTimeout(self.timerShow); 618 | self.timerShow = null; 619 | clearTimeout(self.timerHide); 620 | self.timerHide = null; 621 | 622 | var finishCallbacks = function() { 623 | // trigger any hide method custom callbacks and reset them 624 | $.each(self.callbacks.hide, function(i,c) { c.call(self.$el); }); 625 | self.callbacks.hide = []; 626 | }; 627 | 628 | // hide 629 | if (self.Status == 'shown' || self.Status == 'appearing') { 630 | 631 | self.Status = 'disappearing'; 632 | 633 | var finish = function() { 634 | 635 | self.Status = 'hidden'; 636 | 637 | // detach our content object first, so the next jQuery's remove() call does not unbind its event handlers 638 | if (typeof self.Content == 'object' && self.Content !== null) { 639 | self.Content.detach(); 640 | } 641 | 642 | self.$tooltip.remove(); 643 | self.$tooltip = null; 644 | 645 | // unbind orientationchange, scroll and resize listeners 646 | $(window).off('.'+ self.namespace); 647 | 648 | $('body') 649 | // unbind any auto-closing click/touch listeners 650 | .off('.'+ self.namespace) 651 | .css('overflow-x', self.bodyOverflowX); 652 | 653 | // unbind any auto-closing click/touch listeners 654 | $('body').off('.'+ self.namespace); 655 | 656 | // unbind any auto-closing hover listeners 657 | self.$elProxy.off('.'+ self.namespace + '-autoClose'); 658 | 659 | // call our constructor custom callback function 660 | self.options.functionAfter.call(self.$el, self.$el); 661 | 662 | // call our method custom callbacks functions 663 | finishCallbacks(); 664 | }; 665 | 666 | if (supportsTransitions()) { 667 | 668 | self.$tooltip 669 | .clearQueue() 670 | .removeClass('tooltipster-' + self.options.animation + '-show') 671 | // for transitions only 672 | .addClass('tooltipster-dying'); 673 | 674 | if(self.options.speed > 0) self.$tooltip.delay(self.options.speed); 675 | 676 | self.$tooltip.queue(finish); 677 | } 678 | else { 679 | self.$tooltip 680 | .stop() 681 | .fadeOut(self.options.speed, finish); 682 | } 683 | } 684 | // if the tooltip is already hidden, we still need to trigger the method custom callback 685 | else if(self.Status == 'hidden') { 686 | finishCallbacks(); 687 | } 688 | 689 | return self; 690 | }, 691 | 692 | // the public show() method is actually an alias for the private showNow() method 693 | show: function(callback) { 694 | this._showNow(callback); 695 | return this; 696 | }, 697 | 698 | // 'update' is deprecated in favor of 'content' but is kept for backward compatibility 699 | update: function(c) { 700 | return this.content(c); 701 | }, 702 | content: function(c) { 703 | // getter method 704 | if(typeof c === 'undefined'){ 705 | return this.Content; 706 | } 707 | // setter method 708 | else { 709 | this._update(c); 710 | return this; 711 | } 712 | }, 713 | 714 | reposition: function() { 715 | 716 | var self = this; 717 | 718 | // in case the tooltip has been removed from DOM manually 719 | if ($('body').find(self.$tooltip).length !== 0) { 720 | 721 | // reset width 722 | self.$tooltip.css('width', ''); 723 | 724 | // find variables to determine placement 725 | self.elProxyPosition = self._repositionInfo(self.$elProxy); 726 | var arrowReposition = null, 727 | windowWidth = $(window).width(), 728 | // shorthand 729 | proxy = self.elProxyPosition, 730 | tooltipWidth = self.$tooltip.outerWidth(false), 731 | tooltipInnerWidth = self.$tooltip.innerWidth() + 1, // this +1 stops FireFox from sometimes forcing an additional text line 732 | tooltipHeight = self.$tooltip.outerHeight(false); 733 | 734 | // if this is an tag inside a , all hell breaks loose. Recalculate all the measurements based on coordinates 735 | if (self.$elProxy.is('area')) { 736 | var areaShape = self.$elProxy.attr('shape'), 737 | mapName = self.$elProxy.parent().attr('name'), 738 | map = $('img[usemap="#'+ mapName +'"]'), 739 | mapOffsetLeft = map.offset().left, 740 | mapOffsetTop = map.offset().top, 741 | areaMeasurements = self.$elProxy.attr('coords') !== undefined ? self.$elProxy.attr('coords').split(',') : undefined; 742 | 743 | if (areaShape == 'circle') { 744 | var areaLeft = parseInt(areaMeasurements[0]), 745 | areaTop = parseInt(areaMeasurements[1]), 746 | areaWidth = parseInt(areaMeasurements[2]); 747 | proxy.dimension.height = areaWidth * 2; 748 | proxy.dimension.width = areaWidth * 2; 749 | proxy.offset.top = mapOffsetTop + areaTop - areaWidth; 750 | proxy.offset.left = mapOffsetLeft + areaLeft - areaWidth; 751 | } 752 | else if (areaShape == 'rect') { 753 | var areaLeft = parseInt(areaMeasurements[0]), 754 | areaTop = parseInt(areaMeasurements[1]), 755 | areaRight = parseInt(areaMeasurements[2]), 756 | areaBottom = parseInt(areaMeasurements[3]); 757 | proxy.dimension.height = areaBottom - areaTop; 758 | proxy.dimension.width = areaRight - areaLeft; 759 | proxy.offset.top = mapOffsetTop + areaTop; 760 | proxy.offset.left = mapOffsetLeft + areaLeft; 761 | } 762 | else if (areaShape == 'poly') { 763 | var areaXs = [], 764 | areaYs = [], 765 | areaSmallestX = 0, 766 | areaSmallestY = 0, 767 | areaGreatestX = 0, 768 | areaGreatestY = 0, 769 | arrayAlternate = 'even'; 770 | 771 | for (var i = 0; i < areaMeasurements.length; i++) { 772 | var areaNumber = parseInt(areaMeasurements[i]); 773 | 774 | if (arrayAlternate == 'even') { 775 | if (areaNumber > areaGreatestX) { 776 | areaGreatestX = areaNumber; 777 | if (i === 0) { 778 | areaSmallestX = areaGreatestX; 779 | } 780 | } 781 | 782 | if (areaNumber < areaSmallestX) { 783 | areaSmallestX = areaNumber; 784 | } 785 | 786 | arrayAlternate = 'odd'; 787 | } 788 | else { 789 | if (areaNumber > areaGreatestY) { 790 | areaGreatestY = areaNumber; 791 | if (i == 1) { 792 | areaSmallestY = areaGreatestY; 793 | } 794 | } 795 | 796 | if (areaNumber < areaSmallestY) { 797 | areaSmallestY = areaNumber; 798 | } 799 | 800 | arrayAlternate = 'even'; 801 | } 802 | } 803 | 804 | proxy.dimension.height = areaGreatestY - areaSmallestY; 805 | proxy.dimension.width = areaGreatestX - areaSmallestX; 806 | proxy.offset.top = mapOffsetTop + areaSmallestY; 807 | proxy.offset.left = mapOffsetLeft + areaSmallestX; 808 | } 809 | else { 810 | proxy.dimension.height = map.outerHeight(false); 811 | proxy.dimension.width = map.outerWidth(false); 812 | proxy.offset.top = mapOffsetTop; 813 | proxy.offset.left = mapOffsetLeft; 814 | } 815 | } 816 | 817 | // hardcoding the width and removing the padding fixed an issue with the tooltip width collapsing when the window size is small 818 | if(self.options.fixedWidth === 0) { 819 | self.$tooltip.css({ 820 | 'width': Math.round(tooltipInnerWidth) + 'px', 821 | 'padding-left': '0px', 822 | 'padding-right': '0px' 823 | }); 824 | } 825 | 826 | // our function and global vars for positioning our tooltip 827 | var myLeft = 0, 828 | myLeftMirror = 0, 829 | myTop = 0, 830 | offsetY = parseInt(self.options.offsetY), 831 | offsetX = parseInt(self.options.offsetX), 832 | // this is the arrow position that will eventually be used. It may differ from the position option if the tooltip cannot be displayed in this position 833 | practicalPosition = self.options.position; 834 | 835 | // a function to detect if the tooltip is going off the screen horizontally. If so, reposition the crap out of it! 836 | function dontGoOffScreenX() { 837 | 838 | var windowLeft = $(window).scrollLeft(); 839 | 840 | // if the tooltip goes off the left side of the screen, line it up with the left side of the window 841 | if((myLeft - windowLeft) < 0) { 842 | arrowReposition = myLeft - windowLeft; 843 | myLeft = windowLeft; 844 | } 845 | 846 | // if the tooltip goes off the right of the screen, line it up with the right side of the window 847 | if (((myLeft + tooltipWidth) - windowLeft) > windowWidth) { 848 | arrowReposition = myLeft - ((windowWidth + windowLeft) - tooltipWidth); 849 | myLeft = (windowWidth + windowLeft) - tooltipWidth; 850 | } 851 | } 852 | 853 | // a function to detect if the tooltip is going off the screen vertically. If so, switch to the opposite! 854 | function dontGoOffScreenY(switchTo, switchFrom) { 855 | // if it goes off the top off the page 856 | if(((proxy.offset.top - $(window).scrollTop() - tooltipHeight - offsetY - 12) < 0) && (switchFrom.indexOf('top') > -1)) { 857 | practicalPosition = switchTo; 858 | } 859 | 860 | // if it goes off the bottom of the page 861 | if (((proxy.offset.top + proxy.dimension.height + tooltipHeight + 12 + offsetY) > ($(window).scrollTop() + $(window).height())) && (switchFrom.indexOf('bottom') > -1)) { 862 | practicalPosition = switchTo; 863 | myTop = (proxy.offset.top - tooltipHeight) - offsetY - 12; 864 | } 865 | } 866 | 867 | if(practicalPosition == 'top') { 868 | var leftDifference = (proxy.offset.left + tooltipWidth) - (proxy.offset.left + proxy.dimension.width); 869 | myLeft = (proxy.offset.left + offsetX) - (leftDifference / 2); 870 | myTop = (proxy.offset.top - tooltipHeight) - offsetY - 12; 871 | dontGoOffScreenX(); 872 | dontGoOffScreenY('bottom', 'top'); 873 | } 874 | 875 | if(practicalPosition == 'top-left') { 876 | myLeft = proxy.offset.left + offsetX; 877 | myTop = (proxy.offset.top - tooltipHeight) - offsetY - 12; 878 | dontGoOffScreenX(); 879 | dontGoOffScreenY('bottom-left', 'top-left'); 880 | } 881 | 882 | if(practicalPosition == 'top-right') { 883 | myLeft = (proxy.offset.left + proxy.dimension.width + offsetX) - tooltipWidth; 884 | myTop = (proxy.offset.top - tooltipHeight) - offsetY - 12; 885 | dontGoOffScreenX(); 886 | dontGoOffScreenY('bottom-right', 'top-right'); 887 | } 888 | 889 | if(practicalPosition == 'bottom') { 890 | var leftDifference = (proxy.offset.left + tooltipWidth) - (proxy.offset.left + proxy.dimension.width); 891 | myLeft = proxy.offset.left - (leftDifference / 2) + offsetX; 892 | myTop = (proxy.offset.top + proxy.dimension.height) + offsetY + 12; 893 | dontGoOffScreenX(); 894 | dontGoOffScreenY('top', 'bottom'); 895 | } 896 | 897 | if(practicalPosition == 'bottom-left') { 898 | myLeft = proxy.offset.left + offsetX; 899 | myTop = (proxy.offset.top + proxy.dimension.height) + offsetY + 12; 900 | dontGoOffScreenX(); 901 | dontGoOffScreenY('top-left', 'bottom-left'); 902 | } 903 | 904 | if(practicalPosition == 'bottom-right') { 905 | myLeft = (proxy.offset.left + proxy.dimension.width + offsetX) - tooltipWidth; 906 | myTop = (proxy.offset.top + proxy.dimension.height) + offsetY + 12; 907 | dontGoOffScreenX(); 908 | dontGoOffScreenY('top-right', 'bottom-right'); 909 | } 910 | 911 | if(practicalPosition == 'left') { 912 | myLeft = proxy.offset.left - offsetX - tooltipWidth - 12; 913 | myLeftMirror = proxy.offset.left + offsetX + proxy.dimension.width + 12; 914 | var topDifference = (proxy.offset.top + tooltipHeight) - (proxy.offset.top + proxy.dimension.height); 915 | myTop = proxy.offset.top - (topDifference / 2) - offsetY; 916 | 917 | // if the tooltip goes off boths sides of the page 918 | if((myLeft < 0) && ((myLeftMirror + tooltipWidth) > windowWidth)) { 919 | var borderWidth = parseFloat(self.$tooltip.css('border-width')) * 2, 920 | newWidth = (tooltipWidth + myLeft) - borderWidth; 921 | self.$tooltip.css('width', newWidth + 'px'); 922 | 923 | tooltipHeight = self.$tooltip.outerHeight(false); 924 | myLeft = proxy.offset.left - offsetX - newWidth - 12 - borderWidth; 925 | topDifference = (proxy.offset.top + tooltipHeight) - (proxy.offset.top + proxy.dimension.height); 926 | myTop = proxy.offset.top - (topDifference / 2) - offsetY; 927 | } 928 | 929 | // if it only goes off one side, flip it to the other side 930 | else if(myLeft < 0) { 931 | myLeft = proxy.offset.left + offsetX + proxy.dimension.width + 12; 932 | arrowReposition = 'left'; 933 | } 934 | } 935 | 936 | if(practicalPosition == 'right') { 937 | myLeft = proxy.offset.left + offsetX + proxy.dimension.width + 12; 938 | myLeftMirror = proxy.offset.left - offsetX - tooltipWidth - 12; 939 | var topDifference = (proxy.offset.top + tooltipHeight) - (proxy.offset.top + proxy.dimension.height); 940 | myTop = proxy.offset.top - (topDifference / 2) - offsetY; 941 | 942 | // if the tooltip goes off boths sides of the page 943 | if(((myLeft + tooltipWidth) > windowWidth) && (myLeftMirror < 0)) { 944 | var borderWidth = parseFloat(self.$tooltip.css('border-width')) * 2, 945 | newWidth = (windowWidth - myLeft) - borderWidth; 946 | self.$tooltip.css('width', newWidth + 'px'); 947 | 948 | tooltipHeight = self.$tooltip.outerHeight(false); 949 | topDifference = (proxy.offset.top + tooltipHeight) - (proxy.offset.top + proxy.dimension.height); 950 | myTop = proxy.offset.top - (topDifference / 2) - offsetY; 951 | } 952 | 953 | // if it only goes off one side, flip it to the other side 954 | else if((myLeft + tooltipWidth) > windowWidth) { 955 | myLeft = proxy.offset.left - offsetX - tooltipWidth - 12; 956 | arrowReposition = 'right'; 957 | } 958 | } 959 | 960 | // if arrow is set true, style it and append it 961 | if (self.options.arrow) { 962 | 963 | var arrowClass = 'tooltipster-arrow-' + practicalPosition; 964 | 965 | // set color of the arrow 966 | if(self.options.arrowColor.length < 1) { 967 | var arrowColor = self.$tooltip.css('background-color'); 968 | } 969 | else { 970 | var arrowColor = self.options.arrowColor; 971 | } 972 | 973 | // if the tooltip was going off the page and had to re-adjust, we need to update the arrow's position 974 | if (!arrowReposition) { 975 | arrowReposition = ''; 976 | } 977 | else if (arrowReposition == 'left') { 978 | arrowClass = 'tooltipster-arrow-right'; 979 | arrowReposition = ''; 980 | } 981 | else if (arrowReposition == 'right') { 982 | arrowClass = 'tooltipster-arrow-left'; 983 | arrowReposition = ''; 984 | } 985 | else { 986 | arrowReposition = 'left:'+ Math.round(arrowReposition) +'px;'; 987 | } 988 | 989 | // building the logic to create the border around the arrow of the tooltip 990 | if ((practicalPosition == 'top') || (practicalPosition == 'top-left') || (practicalPosition == 'top-right')) { 991 | var tooltipBorderWidth = parseFloat(self.$tooltip.css('border-bottom-width')), 992 | tooltipBorderColor = self.$tooltip.css('border-bottom-color'); 993 | } 994 | else if ((practicalPosition == 'bottom') || (practicalPosition == 'bottom-left') || (practicalPosition == 'bottom-right')) { 995 | var tooltipBorderWidth = parseFloat(self.$tooltip.css('border-top-width')), 996 | tooltipBorderColor = self.$tooltip.css('border-top-color'); 997 | } 998 | else if (practicalPosition == 'left') { 999 | var tooltipBorderWidth = parseFloat(self.$tooltip.css('border-right-width')), 1000 | tooltipBorderColor = self.$tooltip.css('border-right-color'); 1001 | } 1002 | else if (practicalPosition == 'right') { 1003 | var tooltipBorderWidth = parseFloat(self.$tooltip.css('border-left-width')), 1004 | tooltipBorderColor = self.$tooltip.css('border-left-color'); 1005 | } 1006 | else { 1007 | var tooltipBorderWidth = parseFloat(self.$tooltip.css('border-bottom-width')), 1008 | tooltipBorderColor = self.$tooltip.css('border-bottom-color'); 1009 | } 1010 | 1011 | if (tooltipBorderWidth > 1) { 1012 | tooltipBorderWidth++; 1013 | } 1014 | 1015 | var arrowBorder = ''; 1016 | if (tooltipBorderWidth !== 0) { 1017 | var arrowBorderSize = '', 1018 | arrowBorderColor = 'border-color: '+ tooltipBorderColor +';'; 1019 | if (arrowClass.indexOf('bottom') !== -1) { 1020 | arrowBorderSize = 'margin-top: -'+ Math.round(tooltipBorderWidth) +'px;'; 1021 | } 1022 | else if (arrowClass.indexOf('top') !== -1) { 1023 | arrowBorderSize = 'margin-bottom: -'+ Math.round(tooltipBorderWidth) +'px;'; 1024 | } 1025 | else if (arrowClass.indexOf('left') !== -1) { 1026 | arrowBorderSize = 'margin-right: -'+ Math.round(tooltipBorderWidth) +'px;'; 1027 | } 1028 | else if (arrowClass.indexOf('right') !== -1) { 1029 | arrowBorderSize = 'margin-left: -'+ Math.round(tooltipBorderWidth) +'px;'; 1030 | } 1031 | arrowBorder = ''; 1032 | } 1033 | 1034 | // if the arrow already exists, remove and replace it 1035 | self.$tooltip.find('.tooltipster-arrow').remove(); 1036 | 1037 | // build out the arrow and append it 1038 | var arrowConstruct = '
'+ arrowBorder +'
'; 1039 | self.$tooltip.append(arrowConstruct); 1040 | } 1041 | 1042 | // position the tooltip 1043 | self.$tooltip.css({'top': Math.round(myTop) + 'px', 'left': Math.round(myLeft) + 'px'}); 1044 | } 1045 | 1046 | return self; 1047 | }, 1048 | 1049 | enable: function() { 1050 | this.enabled = true; 1051 | return this; 1052 | }, 1053 | 1054 | disable: function() { 1055 | // hide first, in case the tooltip would not disappear on its own (autoClose false) 1056 | this.hide(); 1057 | this.enabled = false; 1058 | return this; 1059 | }, 1060 | 1061 | destroy: function() { 1062 | 1063 | var self = this; 1064 | 1065 | self.hide(); 1066 | 1067 | // remove the icon, if any 1068 | if(self.$el[0] !== self.$elProxy[0]) self.$elProxy.remove(); 1069 | 1070 | self.$el 1071 | .removeData(self.namespace) 1072 | .off('.'+ self.namespace); 1073 | 1074 | var ns = self.$el.data('tooltipster-ns'); 1075 | 1076 | // if there are no more tooltips on this element 1077 | if(ns.length === 1){ 1078 | 1079 | // old school technique when outerHTML is not supported 1080 | var stringifiedContent = (typeof self.Content === 'string') ? self.Content : $('
').append(self.Content).html(); 1081 | 1082 | self.$el 1083 | .removeClass('tooltipstered') 1084 | .attr('title', stringifiedContent) 1085 | .removeData(self.namespace) 1086 | .removeData('tooltipster-ns') 1087 | .off('.'+ self.namespace); 1088 | } 1089 | else { 1090 | // remove the instance namespace from the list of namespaces of tooltips present on the element 1091 | ns = $.grep(ns, function(el, i){ 1092 | return el !== self.namespace; 1093 | }); 1094 | self.$el.data('tooltipster-ns', ns); 1095 | } 1096 | 1097 | return self; 1098 | }, 1099 | 1100 | elementIcon: function() { 1101 | return (this.$el[0] !== this.$elProxy[0]) ? this.$elProxy[0] : undefined; 1102 | }, 1103 | 1104 | elementTooltip: function() { 1105 | return this.$tooltip ? this.$tooltip[0] : undefined; 1106 | }, 1107 | 1108 | // public methods but for internal use only 1109 | option: function(o) { 1110 | return this.options[o]; 1111 | }, 1112 | status: function(o) { 1113 | return this.Status; 1114 | } 1115 | }; 1116 | 1117 | $.fn[pluginName] = function () { 1118 | 1119 | // for using in closures 1120 | var args = arguments; 1121 | 1122 | // if we are not in the context of jQuery wrapped HTML element(s) : 1123 | // this happens when calling static methods in the form $.fn.tooltipster('methodName'), or when calling $(sel).tooltipster('methodName or options') where $(sel) does not match anything 1124 | if (this.length === 0) { 1125 | 1126 | // if the first argument is a method name 1127 | if (typeof args[0] === 'string') { 1128 | 1129 | var methodIsStatic = true; 1130 | 1131 | // list static methods here (usable by calling $.fn.tooltipster('methodName');) 1132 | switch (args[0]) { 1133 | 1134 | case 'setDefaults': 1135 | // change default options for all future instances 1136 | $.extend(defaults, args[1]); 1137 | break; 1138 | 1139 | default: 1140 | methodIsStatic = false; 1141 | break; 1142 | } 1143 | 1144 | // $.fn.tooltipster('methodName') calls will return true 1145 | if (methodIsStatic) return true; 1146 | // $(sel).tooltipster('methodName') calls will return the list of objects event though it's empty because chaining should work on empty lists 1147 | else return this; 1148 | } 1149 | // the first argument is undefined or an object of options : we are initalizing but there is no element matched by selector 1150 | else { 1151 | // still chainable : same as above 1152 | return this; 1153 | } 1154 | } 1155 | // this happens when calling $(sel).tooltipster('methodName or options') where $(sel) matches one or more elements 1156 | else { 1157 | 1158 | // method calls 1159 | if (typeof args[0] === 'string') { 1160 | 1161 | var v = '#*$~&'; 1162 | 1163 | this.each(function() { 1164 | 1165 | // retrieve the namepaces of the tooltip(s) that exist on that element. We will interact with the first tooltip only. 1166 | var ns = $(this).data('tooltipster-ns'), 1167 | // self represents the instance of the first tooltipster plugin associated to the current HTML object of the loop 1168 | self = ns ? $(this).data(ns[0]) : null; 1169 | 1170 | // if the current element holds a tooltipster instance 1171 | if(self){ 1172 | 1173 | if (typeof self[args[0]] === 'function') { 1174 | var resp = self[args[0]](args[1]); 1175 | } 1176 | else { 1177 | throw new Error('Unknown method .tooltipster("' + args[0] + '")'); 1178 | } 1179 | 1180 | // if the function returned anything other than the instance itself (which implies chaining) 1181 | if (resp !== self){ 1182 | v = resp; 1183 | // return false to stop .each iteration on the first element matched by the selector 1184 | return false; 1185 | } 1186 | } 1187 | else { 1188 | throw new Error('You called Tooltipster\'s "' + args[0] + '" method on an uninitialized element'); 1189 | } 1190 | }); 1191 | 1192 | return (v !== '#*$~&') ? v : this; 1193 | } 1194 | // first argument is undefined or an object : the tooltip is initializing 1195 | else { 1196 | 1197 | var instances = [], 1198 | // is there a defined value for the multiple option in the options object ? 1199 | multipleIsSet = args[0] && typeof args[0].multiple !== 'undefined', 1200 | // if the multople option is set to true, or if it's not defined but set to true in the defaults 1201 | multiple = (multipleIsSet && args[0].multiple) || (!multipleIsSet && defaults.multiple); 1202 | 1203 | // initialize a tooltipster instance for each element if it doesn't already have one or if the multiple option is set, and attach the object to it 1204 | this.each(function () { 1205 | 1206 | var go = false, 1207 | ns = $(this).data('tooltipster-ns'), 1208 | instance = null; 1209 | 1210 | if (!ns) { 1211 | go = true; 1212 | } 1213 | else { 1214 | if(multiple) go = true; 1215 | else console.log('Tooltipster: one or more tooltips are already attached to this element: ignoring. Use the "multiple" option to attach more tooltips.'); 1216 | } 1217 | 1218 | if(go) { 1219 | instance = new Plugin(this, args[0]); 1220 | 1221 | // save the reference of the new instance 1222 | if (!ns) ns = []; 1223 | ns.push(instance.namespace); 1224 | $(this).data('tooltipster-ns', ns) 1225 | 1226 | // save the instance itself 1227 | $(this).data(instance.namespace, instance); 1228 | } 1229 | 1230 | instances.push(instance); 1231 | }); 1232 | 1233 | if(multiple) return instances; 1234 | else return this; 1235 | } 1236 | } 1237 | }; 1238 | 1239 | // quick & dirty compare function (not bijective nor multidimensional) 1240 | function areEqual(a,b) { 1241 | var same = true; 1242 | $.each(a, function(i, el){ 1243 | if(typeof b[i] === 'undefined' || a[i] !== b[i]){ 1244 | same = false; 1245 | return false; 1246 | } 1247 | }); 1248 | return same; 1249 | } 1250 | 1251 | // detect if this device can trigger touch events 1252 | var deviceHasTouchCapability = !!('ontouchstart' in window); 1253 | 1254 | // we'll assume the device has no mouse until we detect any mouse movement 1255 | var deviceHasMouse = false; 1256 | $('body').one('mousemove', function() { 1257 | deviceHasMouse = true; 1258 | }); 1259 | 1260 | function deviceIsPureTouch() { 1261 | return (!deviceHasMouse && deviceHasTouchCapability); 1262 | } 1263 | 1264 | // detecting support for CSS transitions 1265 | function supportsTransitions() { 1266 | var b = document.body || document.documentElement, 1267 | s = b.style, 1268 | p = 'transition'; 1269 | 1270 | if(typeof s[p] == 'string') {return true; } 1271 | 1272 | v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms'], 1273 | p = p.charAt(0).toUpperCase() + p.substr(1); 1274 | for(var i=0; i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('"1d 1e";(8(O){4 a=O.a;a.1f.b.2=8(3,6){4 x=5.9;4 1="";e(4 i=0,d=x.f;i/g,_0x48ca[252]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/\ =/g,_0x48ca[221]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/! =/g,_0x48ca[220]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/\,/g,_0x48ca[257]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/\./g,_0x48ca[197]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/\*/g,_0x48ca[258]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/\;/g,_0x48ca[259]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/\n\s*\n/g,_0x48ca[224]);_0x158ax2f=_0x158ax2f[_0x48ca[115]](/^\s+|\s+$/g,_0x48ca[67]);var _0x158ax31=_0x158ax2f[_0x48ca[78]](_0x48ca[224]);for(var _0x158ax14=0;_0x158ax14<_0x158ax31[_0x48ca[83]];_0x158ax14++){_0x158ax31[_0x158ax14]=_0x158ax31[_0x158ax14][_0x48ca[115]](/\s{2,}/g,_0x48ca[77]);_0x158ax31[_0x158ax14]=trim1(_0x158ax31[_0x158ax14]);var _0x158ax32=_0x158ax31[_0x158ax14][_0x48ca[78]](_0x48ca[77]);for(var _0x158axa=0;_0x158axa<_0x158ax32[_0x48ca[83]];_0x158axa++){if(_0x158ax32[_0x158axa]==_0x48ca[193]){_0x158ax10+=_0x48ca[236]+allstrings[_0x48ca[199]]()+_0x48ca[236];} else {if(faltu[_0x48ca[260]](_0x158ax32[_0x158axa])!=-1){_0x158ax10+=_0x48ca[77];_0x158ax10+=_0x158ax32[_0x158axa];_0x158ax10+=_0x48ca[77];} else {if(/^\d+$/[_0x48ca[261]](_0x158ax32[_0x158axa])||/^-?[0-9]+(\.[0-9]+)?$/[_0x48ca[261]](_0x158ax32[_0x158axa])){_0x158ax10+=_0x158ax32[_0x158axa];} else {if(bangla[_0x48ca[260]](_0x158ax32[_0x158axa])==-1){(bangla[_0x48ca[198]](_0x158ax32[_0x158axa]));} ;var _0x158ax33=bangla[_0x48ca[260]](_0x158ax32[_0x158axa]);_0x158ax10+=variables[_0x158ax33];} ;} ;} ;} ;_0x158ax10+=_0x48ca[224];} ;_0x158ax10=_0x158ax10[_0x48ca[115]](/\n\s*\n/g,_0x48ca[224]);var _0x158ax34=_0x48ca[67];var _0x158ax35=_0x158ax10[_0x48ca[78]](_0x48ca[224]);for(var _0x158ax14=0;_0x158ax14<_0x158ax35[_0x48ca[83]];_0x158ax14++){if(_0x158ax35[_0x158ax14][_0x48ca[260]](_0x48ca[183])!=-1){if(_0x158ax35[_0x158ax14][_0x48ca[260]](_0x48ca[215])!=-1){_0x158ax35[_0x158ax14]=_0x158ax35[_0x158ax14][_0x48ca[115]](_0x48ca[215],_0x48ca[262]);} else {if(_0x158ax35[_0x158ax14+1][_0x48ca[260]](_0x48ca[215])!=-1){_0x158ax35[_0x158ax14+1]=_0x158ax35[_0x158ax14+1][_0x48ca[115]](_0x48ca[215],_0x48ca[262]);} ;} ;} ;if(_0x158ax35[_0x158ax14][_0x48ca[260]](_0x48ca[180])!=-1){var _0x158ax30=_0x158ax35[_0x158ax14][_0x48ca[115]](_0x48ca[263],_0x48ca[264]);var _0x158ax36=_0x158ax30[_0x48ca[115]](_0x48ca[264],_0x48ca[265]);_0x158ax34+=_0x158ax36;} else {_0x158ax34+=_0x158ax35[_0x158ax14];} ;_0x158ax34+=_0x48ca[224];} ;return _0x158ax34;} ;function errorfound(_0x158ax38){} ;function include(_0x158ax3a,_0x158ax3b){return (_0x158ax3a[_0x48ca[260]](_0x158ax3b)!=-1);} ; -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | -------------------------------------------------------------------------------- /tutorial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | চা Script - Tutorials 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 29 | 30 | 31 | 32 | 43 | 44 | 45 |

Short Video Tutorials


46 |

চা স্ক্রিপ্টের সিনটেক্সকে আরও সহজবোধ্য করে তুলে ধরার জন্য কিছু ছোট্ট ভিডিও নির্দেশিকা। আমরা পূর্ণাঙ্গ নির্দেশিকার জন্য কাজ করে যাচ্ছি, আশা করছি অচিরেই আপনাদের কাছে তা পৌঁছে দিতে পারবো।

47 |

These short video tutorials are recorded in order to help people understand the syntax of চা Script. We are currently developing full tutorials which will be available very soon.

48 |
49 | 50 |
51 |

অভ্র ডাউনলোড/ইন্সটল এবং কোড এডিটর পরিচিতি

52 | 53 |

54 |

দেখাও/নাও (Input/Output)

55 | 56 |

57 |

Arithmetic Operators

58 | 59 |

60 |

যদি/নাহলে (If-Else)

61 | 62 |

63 |

চলবে (Loop)

64 | 65 |

66 |

সেট (Array)

67 | 68 |

69 |

ফাংশন (Function)

70 | 71 |

72 |
73 | 74 | 83 | --------------------------------------------------------------------------------