requirejs-rails-plugins 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/javascripts/requirejs_plugins/async.js +42 -0
  5. data/app/assets/javascripts/requirejs_plugins/domReady.js +129 -0
  6. data/app/assets/javascripts/requirejs_plugins/font.js +45 -0
  7. data/app/assets/javascripts/requirejs_plugins/goog.js +38 -0
  8. data/app/assets/javascripts/requirejs_plugins/image.js +53 -0
  9. data/app/assets/javascripts/requirejs_plugins/json.js +61 -0
  10. data/app/assets/javascripts/requirejs_plugins/nokia.js +65 -0
  11. data/app/assets/javascripts/requirejs_plugins/propertyParser.js +43 -0
  12. data/app/assets/javascripts/requirejs_plugins/text.js +332 -0
  13. data/app/assets/stylesheets/requirejs_plugins/application.css +13 -0
  14. data/app/controllers/requirejs_plugins/application_controller.rb +4 -0
  15. data/app/helpers/requirejs_plugins/application_helper.rb +4 -0
  16. data/app/views/layouts/requirejs_plugins/application.html.erb +14 -0
  17. data/config/routes.rb +2 -0
  18. data/lib/requirejs_plugins.rb +4 -0
  19. data/lib/requirejs_plugins/engine.rb +5 -0
  20. data/lib/requirejs_plugins/version.rb +3 -0
  21. data/lib/tasks/requirejs_plugins_tasks.rake +4 -0
  22. data/test/dummy/README.rdoc +261 -0
  23. data/test/dummy/Rakefile +7 -0
  24. data/test/dummy/app/assets/javascripts/application.js +13 -0
  25. data/test/dummy/app/assets/javascripts/content.js +2 -0
  26. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  27. data/test/dummy/app/assets/stylesheets/content.css +4 -0
  28. data/test/dummy/app/controllers/application_controller.rb +3 -0
  29. data/test/dummy/app/controllers/content_controller.rb +4 -0
  30. data/test/dummy/app/helpers/application_helper.rb +2 -0
  31. data/test/dummy/app/helpers/content_helper.rb +2 -0
  32. data/test/dummy/app/views/content/index.html.erb +2 -0
  33. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  34. data/test/dummy/config.ru +4 -0
  35. data/test/dummy/config/application.rb +59 -0
  36. data/test/dummy/config/boot.rb +10 -0
  37. data/test/dummy/config/database.yml +25 -0
  38. data/test/dummy/config/environment.rb +5 -0
  39. data/test/dummy/config/environments/development.rb +37 -0
  40. data/test/dummy/config/environments/production.rb +67 -0
  41. data/test/dummy/config/environments/test.rb +37 -0
  42. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  43. data/test/dummy/config/initializers/inflections.rb +15 -0
  44. data/test/dummy/config/initializers/mime_types.rb +5 -0
  45. data/test/dummy/config/initializers/secret_token.rb +7 -0
  46. data/test/dummy/config/initializers/session_store.rb +8 -0
  47. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/test/dummy/config/locales/en.yml +5 -0
  49. data/test/dummy/config/routes.rb +6 -0
  50. data/test/dummy/db/development.sqlite3 +0 -0
  51. data/test/dummy/log/development.log +58 -0
  52. data/test/dummy/public/404.html +26 -0
  53. data/test/dummy/public/422.html +26 -0
  54. data/test/dummy/public/500.html +25 -0
  55. data/test/dummy/public/favicon.ico +0 -0
  56. data/test/dummy/script/rails +6 -0
  57. data/test/dummy/test/functional/content_controller_test.rb +9 -0
  58. data/test/dummy/test/unit/helpers/content_helper_test.rb +4 -0
  59. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  60. data/test/dummy/tmp/cache/assets/CE4/100/sprockets%2F83ef55e03553719c4bc20f8482d621fe +0 -0
  61. data/test/dummy/tmp/cache/assets/CFA/E70/sprockets%2F4d5132aa20a3ea73f3258e45307c8da3 +0 -0
  62. data/test/dummy/tmp/cache/assets/D0E/EE0/sprockets%2F63f7dbafcb2778ad334c1072468684a1 +0 -0
  63. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  64. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  65. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  66. data/test/dummy/tmp/cache/assets/DD0/480/sprockets%2F5dec288b53bc04a79eee7b7dcc1911e3 +0 -0
  67. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  68. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  69. data/test/integration/navigation_test.rb +10 -0
  70. data/test/requirejs_plugins_test.rb +7 -0
  71. data/test/test_helper.rb +15 -0
  72. metadata +252 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = RequirejsPlugins
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'RequirejsPlugins'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,42 @@
1
+ /** @license
2
+ * RequireJS plugin for async dependency load like JSONP and Google Maps
3
+ * Author: Miller Medeiros
4
+ * Version: 0.1.1 (2011/11/17)
5
+ * Released under the MIT license
6
+ */
7
+ define(function(){
8
+
9
+ var DEFAULT_PARAM_NAME = 'callback',
10
+ _uid = 0;
11
+
12
+ function injectScript(src){
13
+ var s, t;
14
+ s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = src;
15
+ t = document.getElementsByTagName('script')[0]; t.parentNode.insertBefore(s,t);
16
+ }
17
+
18
+ function formatUrl(name, id){
19
+ var paramRegex = /!(.+)/,
20
+ url = name.replace(paramRegex, ''),
21
+ param = (paramRegex.test(name))? name.replace(/.+!/, '') : DEFAULT_PARAM_NAME;
22
+ url += (url.indexOf('?') < 0)? '?' : '&';
23
+ return url + param +'='+ id;
24
+ }
25
+
26
+ function uid() {
27
+ _uid += 1;
28
+ return '__async_req_'+ _uid +'__';
29
+ }
30
+
31
+ return{
32
+ load : function(name, req, onLoad, config){
33
+ if(config.isBuild){
34
+ onLoad(null); //avoid errors on the optimizer
35
+ }else{
36
+ var id = uid();
37
+ window[id] = onLoad; //create a global variable that stores onLoad so callback function can define new module after async load
38
+ injectScript(formatUrl(name, id));
39
+ }
40
+ }
41
+ };
42
+ });
@@ -0,0 +1,129 @@
1
+ /**
2
+ * @license RequireJS domReady 2.0.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
3
+ * Available via the MIT or new BSD license.
4
+ * see: http://github.com/requirejs/domReady for details
5
+ */
6
+ /*jslint */
7
+ /*global require: false, define: false, requirejs: false,
8
+ window: false, clearInterval: false, document: false,
9
+ self: false, setInterval: false */
10
+
11
+
12
+ define(function () {
13
+ 'use strict';
14
+
15
+ var isTop, testDiv, scrollIntervalId,
16
+ isBrowser = typeof window !== "undefined" && window.document,
17
+ isPageLoaded = !isBrowser,
18
+ doc = isBrowser ? document : null,
19
+ readyCalls = [];
20
+
21
+ function runCallbacks(callbacks) {
22
+ var i;
23
+ for (i = 0; i < callbacks.length; i += 1) {
24
+ callbacks[i](doc);
25
+ }
26
+ }
27
+
28
+ function callReady() {
29
+ var callbacks = readyCalls;
30
+
31
+ if (isPageLoaded) {
32
+ //Call the DOM ready callbacks
33
+ if (callbacks.length) {
34
+ readyCalls = [];
35
+ runCallbacks(callbacks);
36
+ }
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Sets the page as loaded.
42
+ */
43
+ function pageLoaded() {
44
+ if (!isPageLoaded) {
45
+ isPageLoaded = true;
46
+ if (scrollIntervalId) {
47
+ clearInterval(scrollIntervalId);
48
+ }
49
+
50
+ callReady();
51
+ }
52
+ }
53
+
54
+ if (isBrowser) {
55
+ if (document.addEventListener) {
56
+ //Standards. Hooray! Assumption here that if standards based,
57
+ //it knows about DOMContentLoaded.
58
+ document.addEventListener("DOMContentLoaded", pageLoaded, false);
59
+ window.addEventListener("load", pageLoaded, false);
60
+ } else if (window.attachEvent) {
61
+ window.attachEvent("onload", pageLoaded);
62
+
63
+ testDiv = document.createElement('div');
64
+ try {
65
+ isTop = window.frameElement === null;
66
+ } catch (e) {}
67
+
68
+ //DOMContentLoaded approximation that uses a doScroll, as found by
69
+ //Diego Perini: http://javascript.nwbox.com/IEContentLoaded/,
70
+ //but modified by other contributors, including jdalton
71
+ if (testDiv.doScroll && isTop && window.external) {
72
+ scrollIntervalId = setInterval(function () {
73
+ try {
74
+ testDiv.doScroll();
75
+ pageLoaded();
76
+ } catch (e) {}
77
+ }, 30);
78
+ }
79
+ }
80
+
81
+ //Check if document already complete, and if so, just trigger page load
82
+ //listeners. Latest webkit browsers also use "interactive", and
83
+ //will fire the onDOMContentLoaded before "interactive" but not after
84
+ //entering "interactive" or "complete". More details:
85
+ //http://dev.w3.org/html5/spec/the-end.html#the-end
86
+ //http://stackoverflow.com/questions/3665561/document-readystate-of-interactive-vs-ondomcontentloaded
87
+ //Hmm, this is more complicated on further use, see "firing too early"
88
+ //bug: https://github.com/requirejs/domReady/issues/1
89
+ //so removing the || document.readyState === "interactive" test.
90
+ //There is still a window.onload binding that should get fired if
91
+ //DOMContentLoaded is missed.
92
+ if (document.readyState === "complete") {
93
+ pageLoaded();
94
+ }
95
+ }
96
+
97
+ /** START OF PUBLIC API **/
98
+
99
+ /**
100
+ * Registers a callback for DOM ready. If DOM is already ready, the
101
+ * callback is called immediately.
102
+ * @param {Function} callback
103
+ */
104
+ function domReady(callback) {
105
+ if (isPageLoaded) {
106
+ callback(doc);
107
+ } else {
108
+ readyCalls.push(callback);
109
+ }
110
+ return domReady;
111
+ }
112
+
113
+ domReady.version = '2.0.1';
114
+
115
+ /**
116
+ * Loader Plugin API method
117
+ */
118
+ domReady.load = function (name, req, onLoad, config) {
119
+ if (config.isBuild) {
120
+ onLoad(null);
121
+ } else {
122
+ domReady(onLoad);
123
+ }
124
+ };
125
+
126
+ /** END OF PUBLIC API **/
127
+
128
+ return domReady;
129
+ });
@@ -0,0 +1,45 @@
1
+ /** @license
2
+ * RequireJS plugin for loading web fonts using the WebFont Loader
3
+ * Author: Miller Medeiros
4
+ * Version: 0.2.0 (2011/12/06)
5
+ * Released under the MIT license
6
+ */
7
+ define(['propertyParser'], function (propertyParser) {
8
+
9
+ var rParts = /^([^,]+),([^\|]+)\|?/;
10
+
11
+ function parseName(name) {
12
+ var data = {},
13
+ vendors = name.split('|'),
14
+ n = vendors.length,
15
+ match;
16
+
17
+ while (n--) {
18
+ match = rParts.exec(vendors[n]);
19
+ data[ match[1] ] = propertyParser.parseProperties(match[2]);
20
+ }
21
+ return data;
22
+ }
23
+
24
+ // API
25
+ return {
26
+
27
+ //example: font!google,families:[Tangerine,Cantarell,Yanone Kaffeesatz:700]
28
+ load : function(name, req, onLoad, config){
29
+ if (config.isBuild) {
30
+ onLoad(null); //avoid errors on the optimizer
31
+ } else {
32
+ var data = parseName(name);
33
+ data.active = onLoad;
34
+ data.inactive = function(){
35
+ onLoad(false);
36
+ };
37
+ req([(document.location.protocol === 'https:'? 'https' : 'http') +'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js'], function(){
38
+ WebFont.load(data);
39
+ });
40
+ }
41
+ }
42
+
43
+ };
44
+
45
+ });
@@ -0,0 +1,38 @@
1
+ /** @license
2
+ * RequireJS plugin for loading Google Ajax API modules thru `google.load`
3
+ * Author: Miller Medeiros
4
+ * Version: 0.2.0 (2011/12/06)
5
+ * Released under the MIT license
6
+ */
7
+ define(['async', 'propertyParser'], function (async, propertyParser) {
8
+
9
+ var rParts = /^([^,]+)(?:,([^,]+))?(?:,(.+))?/;
10
+
11
+ function parseName(name){
12
+ var match = rParts.exec(name),
13
+ data = {
14
+ moduleName : match[1],
15
+ version : match[2] || '1'
16
+ };
17
+ data.settings = propertyParser.parseProperties(match[3]);
18
+ return data;
19
+ }
20
+
21
+ return {
22
+ load : function(name, req, onLoad, config){
23
+ if (config.isBuild) {
24
+ onLoad(null); //avoid errors on the optimizer
25
+ } else {
26
+ var data = parseName(name),
27
+ settings = data.settings;
28
+
29
+ settings.callback = onLoad;
30
+
31
+ req(['async!'+ (document.location.protocol === 'https:'? 'https' : 'http') +'://www.google.com/jsapi'], function(){
32
+ google.load(data.moduleName, data.version, settings);
33
+ });
34
+ }
35
+ }
36
+ };
37
+
38
+ });
@@ -0,0 +1,53 @@
1
+ /** @license
2
+ * RequireJS Image Plugin
3
+ * Author: Miller Medeiros
4
+ * Version: 0.2.2 (2013/02/08)
5
+ * Released under the MIT license
6
+ */
7
+ define(function(){
8
+
9
+ var CACHE_BUST_QUERY_PARAM = 'bust',
10
+ CACHE_BUST_FLAG = '!bust',
11
+ RELATIVE_FLAG = '!rel';
12
+
13
+ function noop(){}
14
+
15
+ function cacheBust(url){
16
+ url = url.replace(CACHE_BUST_FLAG, '');
17
+ url += (url.indexOf('?') < 0)? '?' : '&';
18
+ return url + CACHE_BUST_QUERY_PARAM +'='+ Math.round(2147483647 * Math.random());
19
+ }
20
+
21
+ return {
22
+ load : function(name, req, onLoad, config){
23
+ var img;
24
+ if(config.isBuild){
25
+ onLoad(null); //avoid errors on the optimizer since it can't inline image files
26
+ }else{
27
+ img = new Image();
28
+ img.onerror = function (err) {
29
+ onLoad.error(err);
30
+ };
31
+ img.onload = function(evt){
32
+ onLoad(img);
33
+ try {
34
+ delete img.onload; //release memory - suggested by John Hann
35
+ } catch(err) {
36
+ img.onload = noop; // IE7 :(
37
+ }
38
+ };
39
+ if (name.indexOf(RELATIVE_FLAG) !== -1) {
40
+ //load image relative to module path / baseUrl
41
+ img.src = req.toUrl( name.replace(RELATIVE_FLAG, '') );
42
+ } else {
43
+ img.src = name;
44
+ }
45
+ }
46
+ },
47
+ normalize : function (name, normalize) {
48
+ //used normalize to avoid caching references to a "cache busted" request
49
+ return (name.indexOf(CACHE_BUST_FLAG) === -1)? name : cacheBust(name);
50
+ }
51
+ };
52
+
53
+ });
@@ -0,0 +1,61 @@
1
+ /** @license
2
+ * RequireJS plugin for loading JSON files
3
+ * - depends on Text plugin and it was HEAVILY "inspired" by it as well.
4
+ * Author: Miller Medeiros
5
+ * Version: 0.3.1 (2013/02/04)
6
+ * Released under the MIT license
7
+ */
8
+ define(['text'], function(text){
9
+
10
+ var CACHE_BUST_QUERY_PARAM = 'bust',
11
+ CACHE_BUST_FLAG = '!bust',
12
+ jsonParse = (typeof JSON !== 'undefined' && typeof JSON.parse === 'function')? JSON.parse : function(val){
13
+ return eval('('+ val +')'); //quick and dirty
14
+ },
15
+ buildMap = {};
16
+
17
+ function cacheBust(url){
18
+ url = url.replace(CACHE_BUST_FLAG, '');
19
+ url += (url.indexOf('?') < 0)? '?' : '&';
20
+ return url + CACHE_BUST_QUERY_PARAM +'='+ Math.round(2147483647 * Math.random());
21
+ }
22
+
23
+ //API
24
+ return {
25
+
26
+ load : function(name, req, onLoad, config) {
27
+ if ( config.isBuild && (config.inlineJSON === false || name.indexOf(CACHE_BUST_QUERY_PARAM +'=') !== -1) ) {
28
+ //avoid inlining cache busted JSON or if inlineJSON:false
29
+ onLoad(null);
30
+ } else {
31
+ text.get(req.toUrl(name), function(data){
32
+ if (config.isBuild) {
33
+ buildMap[name] = data;
34
+ onLoad(data);
35
+ } else {
36
+ onLoad(jsonParse(data));
37
+ }
38
+ },
39
+ onLoad.error, {
40
+ accept: 'application/json'
41
+ }
42
+ );
43
+ }
44
+ },
45
+
46
+ normalize : function (name, normalize) {
47
+ //used normalize to avoid caching references to a "cache busted" request
48
+ return (name.indexOf(CACHE_BUST_FLAG) === -1)? name : cacheBust(name);
49
+ },
50
+
51
+ //write method based on RequireJS official text plugin by James Burke
52
+ //https://github.com/jrburke/requirejs/blob/master/text.js
53
+ write : function(pluginName, moduleName, write){
54
+ if(moduleName in buildMap){
55
+ var content = buildMap[moduleName];
56
+ write('define("'+ pluginName +'!'+ moduleName +'", function(){ return '+ content +';});\n');
57
+ }
58
+ }
59
+
60
+ };
61
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * RequireJS plugin for loading Nokia Maps API features thru `nokia.Features.load`
3
+ * @author Bogumil Wrona
4
+ * @license Released under the MIT license
5
+ */
6
+
7
+
8
+ /**
9
+ * RequireJS Plugin
10
+ * @param {Array} nokiaLoader module which has defined path and shim
11
+ * @example
12
+
13
+ require.config({
14
+ waitSeconds: 15,
15
+ paths: {
16
+ nokiaLoader: 'http://api.maps.nokia.com/2.2.4/jsl.js?blank=true',
17
+ domReady: 'requirejs_plugins/domReady',
18
+ nokia: 'requirejs_plugins/nokia'
19
+ },
20
+ shim: {
21
+ nokiaLoader: {
22
+ exports: 'nokia'
23
+ }
24
+ }
25
+ });
26
+ require(['nokia!', 'domReady!'], function() {
27
+ var map = new nokia.maps.map.Display(document.getElementById('map'), {
28
+ center: [52.521542, 13.382178],
29
+ zoomLevel: 6,
30
+ components: [
31
+ new nokia.maps.map.component.Behavior(),
32
+ new nokia.maps.map.component.TypeSelector(),
33
+ new nokia.maps.map.component.DistanceMeasurement(),
34
+ new nokia.maps.map.component.Overview()
35
+ ]
36
+ });
37
+ });
38
+ */
39
+ define(['nokiaLoader'], function(nokia) {
40
+ var _uid = 0,
41
+ DEFAULT_MODULES = ['all'],
42
+ uid = function() {
43
+ _uid +=1;
44
+ return '__async_nokia_features_' + _uid + '__';
45
+ },
46
+ load = function(name, req, onLoad, config) {
47
+ if(config.isBuild) {
48
+ onLoad(null);
49
+ } else {
50
+ var id = uid(),
51
+ features = ('' !== name) ? name.split(',') : DEFAULT_MODULES;
52
+ window[id] = onLoad;
53
+ nokia.Features.load(nokia.Features.getFeaturesFromMatrix(features), function() {
54
+ window[id]();
55
+ }, function() {
56
+ console && console.log && console.log('ERROR while loading nokia map api module(s)');
57
+ }, document, false);
58
+ }
59
+ } ;
60
+
61
+ return {
62
+ load: load
63
+ }
64
+
65
+ });