├── .gitignore ├── Gruntfile.js ├── demo ├── css │ ├── demo.css │ └── reset.css ├── js │ └── demo.js └── index.html ├── jquery.ratyli.min.js ├── README.md ├── jquery.ratyli.js └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(grunt) { 4 | 5 | grunt.initConfig({ 6 | connect: { 7 | server: { 8 | options: { 9 | port: 9000, 10 | base: '', 11 | } 12 | } 13 | }, 14 | uglify: { 15 | target: { 16 | banner: 'Ratyli: jquery rating plugin - (c) 2015 Peter Varga [info@vargapeter.com] - released under the Apache 2.0 license', 17 | files: { 18 | 'jquery.ratyli.min.js': ['jquery.ratyli.js'] 19 | } 20 | } 21 | }, 22 | watch: { 23 | files: ['jquery.ratyli.js'], 24 | tasks: ['uglify'] 25 | } 26 | }); 27 | 28 | 29 | 30 | grunt.loadNpmTasks('grunt-contrib-watch'); 31 | grunt.loadNpmTasks('grunt-contrib-connect'); 32 | grunt.loadNpmTasks('grunt-contrib-uglify'); 33 | 34 | grunt.registerTask('default', ['connect','watch']); 35 | }; -------------------------------------------------------------------------------- /demo/css/demo.css: -------------------------------------------------------------------------------- 1 | /* No CSS needed, but you can pimp the container and the signs as you wish. */ 2 | 3 | 4 | /* all sign style */ 5 | .ratyli .rate{color: #ccc; font-size: 24px;} 6 | 7 | /* empty sign style */ 8 | .ratyli .rate-empty{color: #666;} 9 | 10 | /* full sign style after rating*/ 11 | .ratyli.rated .rate-full{color: #fe5845;} 12 | 13 | /* active signs (hover)*/ 14 | .ratyli .rate-active{color: #a94039;} 15 | 16 | 17 | 18 | /* layout styles (only for demo)*/ 19 | body{font-family: sans-serif; background:#222; } 20 | h1{color:#00dd9a; text-align:center; font-size:24px; margin:30px 0;} 21 | h2{color:#fe5845; font-weight:300; font-size:16px; margin:15px 0;} 22 | p{clear:both; color: #ccc; text-align:center; padding:50px 0;} 23 | footer p{font-size: 80%} 24 | a{color:#00dd9a} 25 | .demo{float:left; width:18%; padding:30px 1%; text-align:center;} 26 | @media screen and (max-width: 920px) { 27 | .demo{float:none; width:90%; padding:20px 5%;} 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /demo/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } -------------------------------------------------------------------------------- /demo/js/demo.js: -------------------------------------------------------------------------------- 1 | /* GitHub: https://github.com/peet86/Ratyli */ 2 | 3 | $(function() { 4 | // Default 5 | $("#demo1 .ratyli").ratyli(); 6 | 7 | // Configure with Datasets 8 | $("#demo2 .ratyli").ratyli(); 9 | 10 | // Configure with JS 11 | $("#demo3 .ratyli").ratyli({rate:3,max:7}); 12 | 13 | // Custom Signs 14 | $("#demo4 .ratyli").ratyli(); 15 | 16 | // Font Awesome Signs 17 | $("#demo5 .ratyli").ratyli({ 18 | full:"", 19 | empty:"", 20 | 21 | }); 22 | 23 | // Rated Callback 24 | $("#demo6 .ratyli").ratyli({ 25 | onRated:function(value,init){ 26 | // rating callback 27 | if(!init) alert(value); // prevent run at init 28 | }, 29 | }); 30 | 31 | // Sign Callbacks: 32 | $("#demo7 .ratyli").ratyli({ 33 | onSignClick:function(value,target){ 34 | // sign click event callback 35 | alert("clicked: "+target); 36 | }, 37 | onSignEnter:function(value,target){ 38 | // sign mouseenter event callback 39 | console.log("enter : "+value); 40 | }, 41 | onSignLeave:function(value,target){ 42 | // sign mouseleave event callback 43 | console.log("leave : "+target); 44 | }, 45 | }); 46 | 47 | // Custom cursor 48 | $("#demo8 .ratyli").ratyli({cursor:"crosshair"}); 49 | 50 | // Disabled 51 | $("#demo9 .ratyli").ratyli({disable:true}); 52 | 53 | // Unrateable 54 | $("#demo10 .ratyli").ratyli({unrateable:true}); 55 | 56 | 57 | }); -------------------------------------------------------------------------------- /jquery.ratyli.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.ratyli=function(b,c){var d=this;d.$el=a(b),d.el=b,d.$el.data("ratyli",d),d.init=function(){d.options=a.extend({},a.ratyli.defaultOptions,c),d.options=a.extend({},d.options,d.$el.data()),d.set(d.options.rate,!0),d.$el.on("click","> *",function(b){if(!d.options.disable){var c=b.target;"SPAN"!=c.tagName&&(c=c.parentNode),d.options.onSignClick.call(d,c);var e=a(c).prevAll().length+1;d.set(e)}}),d.$el.on("mouseenter","> *",function(b){var c=b.target;"SPAN"!=c.tagName&&(c=c.parentNode),d.options.disable||(a(c).addClass("rate-active"),a(c).prevAll().addClass("rate-active")),d.options.onSignEnter.apply(null,[d.options.rate,c])}),d.$el.on("mouseleave","> *",function(b){var c=b.target;"SPAN"!=c.tagName&&(c=c.parentNode),d.options.disable||(a(c).removeClass("rate-active"),a(c).prevAll().removeClass("rate-active")),d.options.onSignLeave.apply(null,[d.options.rate,c])})},d.set=function(a,b){(0>a||a%1!=0||a>d.options.ratemax)&&(a=0),1!=a||1!=d.options.rate||1!=d.options.unrateable||b||(a=0),d.options.rate=a,d.$el.html(""),0!=d.options.rate&&d.$el.attr("data-rate",d.options.rate),d.$el.attr("data-ratemax",d.options.ratemax);for(var c=0;c"+d.options[a]+""},d.init()},a.ratyli.defaultOptions={disable:!1,unrateable:!1,full:"★",empty:"☆",cursor:"default",rate:0,ratemax:5,onSignEnter:function(){},onSignLeave:function(){},onSignClick:function(){},onRated:function(){}},a.fn.ratyli=function(b){return this.each(function(){new a.ratyli(this,b)})}}(jQuery); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ratyli: Simple jQuery Rating Plugin 2 | 3 | ### Output: 4 | ★★★☆☆ 5 | 6 | ### HTML 7 | ```html 8 | 9 | ``` 10 | 11 | ### JS 12 | ```js 13 | $(function() { 14 | $('.ratyli').ratyli(); 15 | }); 16 | ``` 17 | 18 | ### Demo & Examples 19 | 20 | http://codepen.io/peet86/pen/LEzrYy (CodePen) 21 | 22 | ###Quick start: 23 | Incude the latest jQuery library and the jquery.ratyli.min.js script in to your HTML `
` or before the `` tag: 24 | ```html 25 | 26 | ``` 27 | 28 | 29 | ### CSS 30 | No CSS required, but you can pimp your ratings with these CSS selectors: 31 | ```css 32 | .ratyli{} /* container style*/ 33 | .ratyli.rated{} /* container style after rating*/ 34 | .ratyli .rate{} /* sign style*/ 35 | .ratyli .rate-active{} /* sign hover style */ 36 | .ratyli .rate-full{} /* full sign style */ 37 | .ratyli .rate-empty{} /* empty sign style */ 38 | /*etc..*/ 39 | ``` 40 | Check the demo and play with the examples: 41 | http://codepen.io/peet86/pen/LEzrYy (CodePen) 42 | 43 | ### Font Awesome 44 | You can use the amazing Font Awesome icons as rating signs easily: 45 | ```js 46 | $(".ratyli").ratyli({ 47 | full:"", 48 | empty:"", 49 | }); 50 | ``` 51 | 52 | ### Updates 53 | 54 | #### v0.3 (24.11.2015) 55 | - unrateable attribute 56 | - html5 data-rate and data-ratemax attributes 57 | - other small fixes 58 | 59 | #### v0.2.1 (09.02.2015) 60 | - rated CSS selector fix 61 | 62 | #### v0.2 (09.02.2015) 63 | - Font Awesome fix 64 | - interactive parameter replaced with disabled 65 | 66 | ## Notes 67 | * Requires jQuery 1.7+. 68 | * Works in all A-grade browsers and IE9+. 69 | * The name inspired by the famous hungarian food: Ratyli. ;) 70 | 71 | ## License 72 | This plugin is available under Apache 2.0 license. 73 | 74 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DEMO 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

Ratyli Demo

18 | 19 |
20 |

Default

21 | 22 |
23 | 24 |
25 |

Configure with Datasets

26 | 27 |
28 | 29 |
30 |

Configure with JS

31 | 32 |
33 | 34 |
35 |

Custom Signs

36 | 37 |
38 | 39 |
40 |

Font Awesome Signs

41 | 42 |
43 | 44 |
45 |

Rated Callback

46 | 47 |
48 | 49 |
50 |

Sign Callbacks

51 | 52 |
53 | 54 |
55 |

Custom cursor

56 | 57 |
58 | 59 |
60 |

Disabled

61 | 62 |
63 | 64 |
65 |

Unrateable

66 | 67 |
68 | 69 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /jquery.ratyli.js: -------------------------------------------------------------------------------- 1 | // Ratyli: jquery rating plugin 2 | // version 0.2.1 3 | // (c) 2015 Peter Varga [info@vargapeter.com] 4 | // released under the Apache 2.0 license 5 | (function($){ 6 | $.ratyli = function(el, options){ 7 | var base = this; 8 | base.$el = $(el); 9 | base.el = el; 10 | 11 | base.$el.data("ratyli", base); 12 | 13 | base.init = function(){ 14 | // extend with parameters 15 | base.options = $.extend({},$.ratyli.defaultOptions, options); 16 | 17 | // extend with html5 dataset 18 | base.options =$.extend({},base.options,base.$el.data()); 19 | 20 | // for the loop 21 | base.set(base.options.rate,true); 22 | 23 | // event listeners for rating signs 24 | base.$el.on("click","> *",function(e){ 25 | if(!base.options.disable){ 26 | var target= e.target; 27 | if(target.tagName!="SPAN") target=target.parentNode; 28 | 29 | base.options.onSignClick.call(base,target); 30 | var val=$(target).prevAll().length+1; 31 | 32 | base.set(val); 33 | } 34 | }); 35 | 36 | base.$el.on("mouseenter","> *",function(e){ 37 | var target= e.target; 38 | if(target.tagName!="SPAN") target=target.parentNode; 39 | 40 | if(!base.options.disable){ 41 | $(target).addClass("rate-active"); 42 | $(target).prevAll().addClass("rate-active"); 43 | } 44 | base.options.onSignEnter.apply(null,[base.options.rate,target]); 45 | }); 46 | 47 | base.$el.on("mouseleave","> *",function(e){ 48 | var target= e.target; 49 | if(target.tagName!="SPAN") target=target.parentNode; 50 | 51 | if(!base.options.disable){ 52 | $(target).removeClass("rate-active"); 53 | $(target).prevAll().removeClass("rate-active"); 54 | } 55 | base.options.onSignLeave.apply(null,[base.options.rate,target]); 56 | }); 57 | 58 | }; 59 | 60 | base.set=function(val,init){ 61 | if(val<0 || (val % 1 != 0) || val>base.options.ratemax) val=0; // reset to 0. 62 | 63 | if(val==1 && base.options.rate==1 && base.options.unrateable==true && !init){ 64 | val=0; 65 | } 66 | 67 | base.options.rate=val; 68 | 69 | // reset html 70 | base.$el.html(""); 71 | 72 | // set data-rate 73 | if (base.options.rate!=0) base.$el.attr("data-rate",base.options.rate); 74 | 75 | // set data-ratemax 76 | base.$el.attr("data-ratemax",base.options.ratemax); 77 | 78 | 79 | // generate signs 80 | var i=0; 81 | while (i < base.options.ratemax) { 82 | var tmp=""; 83 | if(i"+base.options[type]+""; 107 | }; 108 | 109 | base.init(); 110 | 111 | }; 112 | 113 | $.ratyli.defaultOptions = { 114 | disable: false, 115 | unrateable: false, 116 | full: "★", 117 | empty: "☆", 118 | cursor:"default", 119 | rate:0, 120 | ratemax:5, 121 | onSignEnter:function(){}, 122 | onSignLeave:function(){}, 123 | onSignClick:function(){}, 124 | onRated:function(){} 125 | }; 126 | 127 | $.fn.ratyli = function(options){ 128 | return this.each(function(){ 129 | (new $.ratyli(this, options)); 130 | }); 131 | }; 132 | 133 | })(jQuery); 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | --------------------------------------------------------------------------------