pdfjs-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +2 -0
  6. data/app/helpers/pdfjs/viewer_helper.rb +162 -0
  7. data/lib/pdfjs-rails.rb +13 -0
  8. data/lib/pdfjs-rails/version.rb +5 -0
  9. data/pdfjs-rails.gemspec +17 -0
  10. data/vendor/assets/images/annotation-check.svg +3 -0
  11. data/vendor/assets/images/annotation-comment.svg +3 -0
  12. data/vendor/assets/images/annotation-text.svg +46 -0
  13. data/vendor/assets/images/loading-icon.gif +0 -0
  14. data/vendor/assets/images/texture.png +0 -0
  15. data/vendor/assets/images/toolbarButton-bookmark.png +0 -0
  16. data/vendor/assets/images/toolbarButton-download.png +0 -0
  17. data/vendor/assets/images/toolbarButton-fullscreen.png +0 -0
  18. data/vendor/assets/images/toolbarButton-menuArrows.png +0 -0
  19. data/vendor/assets/images/toolbarButton-openFile.png +0 -0
  20. data/vendor/assets/images/toolbarButton-pageDown-rtl.png +0 -0
  21. data/vendor/assets/images/toolbarButton-pageDown.png +0 -0
  22. data/vendor/assets/images/toolbarButton-pageUp-rtl.png +0 -0
  23. data/vendor/assets/images/toolbarButton-pageUp.png +0 -0
  24. data/vendor/assets/images/toolbarButton-print.png +0 -0
  25. data/vendor/assets/images/toolbarButton-search.png +0 -0
  26. data/vendor/assets/images/toolbarButton-sidebarToggle.png +0 -0
  27. data/vendor/assets/images/toolbarButton-viewOutline.png +0 -0
  28. data/vendor/assets/images/toolbarButton-viewThumbnail.png +0 -0
  29. data/vendor/assets/images/toolbarButton-zoomIn.png +0 -0
  30. data/vendor/assets/images/toolbarButton-zoomOut.png +0 -0
  31. data/vendor/assets/javascripts/compatibility.js +413 -0
  32. data/vendor/assets/javascripts/l10n.js +322 -0
  33. data/vendor/assets/javascripts/pdf.js +35257 -0
  34. data/vendor/assets/javascripts/viewer.js +2297 -0
  35. data/vendor/assets/stylesheets/viewer.css.erb +1298 -0
  36. metadata +80 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pdfjs-rails.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Robert Lail
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Pdfjs::Rails
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'pdfjs-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install pdfjs-rails
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,162 @@
1
+ module Pdfjs
2
+ module ViewerHelper
3
+
4
+ def pdf_viewer(filename)
5
+ html = <<-HTML
6
+ <div id="outerContainer" dir="ltr">
7
+
8
+ <div id="sidebarContainer">
9
+ <div id="toolbarSidebar" class="splitToolbarButton toggled">
10
+ <button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" tabindex="1" data-l10n-id="thumbs">
11
+ <span data-l10n-id="thumbs_label">Thumbnails</span>
12
+ </button>
13
+ <button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="2" data-l10n-id="outline">
14
+ <span data-l10n-id="outline_label">Document Outline</span>
15
+ </button>
16
+ <button id="viewSearch" class="toolbarButton group hidden" title="Search Document" tabindex="3" data-l10n-id="search_panel">
17
+ <span data-l10n-id="search_panel_label">Search Document</span>
18
+ </button>
19
+ </div>
20
+ <div id="sidebarContent">
21
+ <div id="thumbnailView">
22
+ </div>
23
+ <div id="outlineView" class="hidden">
24
+ </div>
25
+ <div id="searchView" class="hidden">
26
+ <div id="searchToolbar">
27
+ <input id="searchTermsInput" class="toolbarField">
28
+ <button id="searchButton" class="textButton toolbarButton" data-l10n-id="search">Find</button>
29
+ </div>
30
+ <div id="searchResults"></div>
31
+ </div>
32
+ </div>
33
+ </div> <!-- sidebarContainer -->
34
+
35
+ <div id="mainContainer">
36
+ <div class="toolbar">
37
+ <div id="toolbarContainer">
38
+
39
+ <div id="toolbarViewer">
40
+ <div id="toolbarViewerLeft">
41
+ <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="4" data-l10n-id="toggle_slider">
42
+ <span data-l10n-id="toggle_slider_label">Toggle Sidebar</span>
43
+ </button>
44
+ <div class="toolbarButtonSpacer"></div>
45
+ <div class="splitToolbarButton">
46
+ <button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="5" data-l10n-id="previous">
47
+ <span data-l10n-id="previous_label">Previous</span>
48
+ </button>
49
+ <div class="splitToolbarButtonSeparator"></div>
50
+ <button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="6" data-l10n-id="next">
51
+ <span data-l10n-id="next_label">Next</span>
52
+ </button>
53
+ </div>
54
+ <label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
55
+ <input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="7">
56
+ </input>
57
+ <span id="numPages" class="toolbarLabel"></span>
58
+ </div>
59
+ <div id="toolbarViewerRight">
60
+ <input id="fileInput" class="fileInput" type="file" oncontextmenu="return false;" style="visibility: hidden; position: fixed; right: 0; top: 0" />
61
+
62
+
63
+ <button id="fullscreen" class="toolbarButton fullscreen" title="Fullscreen" tabindex="11" data-l10n-id="fullscreen">
64
+ <span data-l10n-id="fullscreen_label">Fullscreen</span>
65
+ </button>
66
+
67
+ <button id="openFile" class="toolbarButton openFile" title="Open File" tabindex="12" data-l10n-id="open_file">
68
+ <span data-l10n-id="open_file_label">Open</span>
69
+ </button>
70
+
71
+ <button id="print" class="toolbarButton print" title="Print" tabindex="13" data-l10n-id="print">
72
+ <span data-l10n-id="print_label">Print</span>
73
+ </button>
74
+
75
+ <button id="download" class="toolbarButton download" title="Download" tabindex="14" data-l10n-id="download">
76
+ <span data-l10n-id="download_label">Download</span>
77
+ </button>
78
+ <!-- <div class="toolbarButtonSpacer"></div> -->
79
+ <a href="#" id="viewBookmark" class="toolbarButton bookmark" title="Current view (copy or open in new window)" tabindex="15" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a>
80
+ </div>
81
+ <div class="outerCenter">
82
+ <div class="innerCenter" id="toolbarViewerMiddle">
83
+ <div class="splitToolbarButton">
84
+ <button class="toolbarButton zoomOut" title="Zoom Out" tabindex="8" data-l10n-id="zoom_out">
85
+ <span data-l10n-id="zoom_out_label">Zoom Out</span>
86
+ </button>
87
+ <div class="splitToolbarButtonSeparator"></div>
88
+ <button class="toolbarButton zoomIn" title="Zoom In" tabindex="9" data-l10n-id="zoom_in">
89
+ <span data-l10n-id="zoom_in_label">Zoom In</span>
90
+ </button>
91
+ </div>
92
+ <span id="scaleSelectContainer" class="dropdownToolbarButton">
93
+ <select id="scaleSelect" title="Zoom" oncontextmenu="return false;" tabindex="10" data-l10n-id="zoom">
94
+ <option id="pageAutoOption" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
95
+ <option id="pageActualOption" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
96
+ <option id="pageFitOption" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
97
+ <option id="pageWidthOption" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
98
+ <option id="customScaleOption" value="custom"></option>
99
+ <option value="0.5">50%</option>
100
+ <option value="0.75">75%</option>
101
+ <option value="1">100%</option>
102
+ <option value="1.25">125%</option>
103
+ <option value="1.5">150%</option>
104
+ <option value="2">200%</option>
105
+ </select>
106
+ </span>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ </div>
112
+
113
+ <menu type="context" id="viewerContextMenu">
114
+ <menuitem label="Rotate Counter-Clockwise" id="page_rotate_ccw"
115
+ data-l10n-id="page_rotate_ccw" ></menuitem>
116
+ <menuitem label="Rotate Clockwise" id="page_rotate_cw"
117
+ data-l10n-id="page_rotate_cw" ></menuitem>
118
+ </menu>
119
+
120
+ <div id="viewerContainer">
121
+ <div id="viewer" contextmenu="viewerContextMenu"></div>
122
+ </div>
123
+
124
+ <div id="loadingBox">
125
+ <div id="loading"></div>
126
+ <div id="loadingBar"><div class="progress"></div></div>
127
+ </div>
128
+
129
+ <div id="errorWrapper" hidden='true'>
130
+ <div id="errorMessageLeft">
131
+ <span id="errorMessage"></span>
132
+ <button id="errorShowMore" onclick="" oncontextmenu="return false;" data-l10n-id="error_more_info">
133
+ More Information
134
+ </button>
135
+ <button id="errorShowLess" onclick="" oncontextmenu="return false;" data-l10n-id="error_less_info" hidden='true'>
136
+ Less Information
137
+ </button>
138
+ </div>
139
+ <div id="errorMessageRight">
140
+ <button id="errorClose" oncontextmenu="return false;" data-l10n-id="error_close">
141
+ Close
142
+ </button>
143
+ </div>
144
+ <div class="clearBoth"></div>
145
+ <textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea>
146
+ </div>
147
+ </div> <!-- mainContainer -->
148
+
149
+ </div> <!-- outerContainer -->
150
+
151
+ <script type="text/javascript">
152
+ document.addEventListener('DOMContentLoaded', function() {
153
+ PDFView.open(#{filename.to_json}, 0);
154
+ });
155
+ </script>
156
+ HTML
157
+
158
+ html.html_safe
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,13 @@
1
+ require "pdfjs-rails/version"
2
+
3
+ module Pdfjs
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ paths["app/helpers"] = "lib/helpers"
7
+ end
8
+ end
9
+ end
10
+
11
+ ActiveSupport.on_load(:action_view) do
12
+ include Pdfjs::ViewerHelper
13
+ end
@@ -0,0 +1,5 @@
1
+ module Pdfjs
2
+ module Rails
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/pdfjs-rails/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Robert Lail"]
6
+ gem.email = ["robert.lail@cph.org"]
7
+ gem.description = %q{A gem for plugging pdf.js into a Rails application}
8
+ gem.summary = %q{A gem for plugging pdf.js into a Rails application}
9
+ gem.homepage = "https://github.com/concordia-publishing-house/pdfjs-rails"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "pdfjs-rails"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Pdfjs::Rails::VERSION
17
+ end
@@ -0,0 +1,3 @@
1
+ <svg height="40" width="40" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M2.379,14.729 5.208,11.899 12.958,19.648 25.877,6.733 28.707,9.561 12.958,25.308z" fill="#333333"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg height="40" width="40" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M16,5.333c-7.732,0-14,4.701-14,10.5c0,1.982,0.741,3.833,2.016,5.414L2,25.667l5.613-1.441c2.339,1.317,5.237,2.107,8.387,2.107c7.732,0,14-4.701,14-10.5C30,10.034,23.732,5.333,16,5.333z" fill="#333333"></path>
3
+ </svg>
@@ -0,0 +1,46 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="no"?>
2
+ <svg
3
+ xmlns:cc="http://creativecommons.org/ns#"
4
+ xmlns:svg="http://www.w3.org/2000/svg"
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ height="40"
7
+ width="40"
8
+ id="svg2995"
9
+ version="1.1">
10
+
11
+ <rect
12
+ style="fill:#f1e47b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-opacity:1"
13
+ id="rect3009"
14
+ width="30.169491"
15
+ height="24.576269"
16
+ x="4.237288"
17
+ y="6.7796612" />
18
+ <rect
19
+ style="fill:#000000;fill-opacity:1;stroke:none"
20
+ id="rect3781"
21
+ width="23.38983"
22
+ height="1.1864407"
23
+ x="7.6271186"
24
+ y="11.389831" />
25
+ <rect
26
+ style="fill:#000000;fill-opacity:1;stroke:none"
27
+ id="rect3781-1"
28
+ width="23.38983"
29
+ height="0.67796612"
30
+ x="7.6271191"
31
+ y="21.61017" />
32
+ <rect
33
+ style="fill:#000000;fill-opacity:1;stroke:none"
34
+ id="rect3781-7"
35
+ width="23.38983"
36
+ height="0.67796612"
37
+ x="7.4576273"
38
+ y="26.152542" />
39
+ <rect
40
+ style="fill:#000000;fill-opacity:1;stroke:none"
41
+ id="rect3781-1-4"
42
+ width="23.38983"
43
+ height="0.67796612"
44
+ x="7.6271186"
45
+ y="17.033899" />
46
+ </svg>
Binary file
@@ -0,0 +1,413 @@
1
+ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
+ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
3
+ /* Copyright 2012 Mozilla Foundation
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ 'use strict';
19
+
20
+ // Checking if the typed arrays are supported
21
+ (function checkTypedArrayCompatibility() {
22
+ if (typeof Uint8Array !== 'undefined') {
23
+ // some mobile versions do not support subarray (e.g. safari 5 / iOS)
24
+ if (typeof Uint8Array.prototype.subarray === 'undefined') {
25
+ Uint8Array.prototype.subarray = function subarray(start, end) {
26
+ return new Uint8Array(this.slice(start, end));
27
+ };
28
+ Float32Array.prototype.subarray = function subarray(start, end) {
29
+ return new Float32Array(this.slice(start, end));
30
+ };
31
+ }
32
+
33
+ // some mobile version might not support Float64Array
34
+ if (typeof Float64Array === 'undefined')
35
+ window.Float64Array = Float32Array;
36
+
37
+ return;
38
+ }
39
+
40
+ function subarray(start, end) {
41
+ return new TypedArray(this.slice(start, end));
42
+ }
43
+
44
+ function setArrayOffset(array, offset) {
45
+ if (arguments.length < 2)
46
+ offset = 0;
47
+ for (var i = 0, n = array.length; i < n; ++i, ++offset)
48
+ this[offset] = array[i] & 0xFF;
49
+ }
50
+
51
+ function TypedArray(arg1) {
52
+ var result;
53
+ if (typeof arg1 === 'number') {
54
+ result = [];
55
+ for (var i = 0; i < arg1; ++i)
56
+ result[i] = 0;
57
+ } else
58
+ result = arg1.slice(0);
59
+
60
+ result.subarray = subarray;
61
+ result.buffer = result;
62
+ result.byteLength = result.length;
63
+ result.set = setArrayOffset;
64
+
65
+ if (typeof arg1 === 'object' && arg1.buffer)
66
+ result.buffer = arg1.buffer;
67
+
68
+ return result;
69
+ }
70
+
71
+ window.Uint8Array = TypedArray;
72
+
73
+ // we don't need support for set, byteLength for 32-bit array
74
+ // so we can use the TypedArray as well
75
+ window.Uint32Array = TypedArray;
76
+ window.Int32Array = TypedArray;
77
+ window.Uint16Array = TypedArray;
78
+ window.Float32Array = TypedArray;
79
+ window.Float64Array = TypedArray;
80
+ })();
81
+
82
+ // Object.create() ?
83
+ (function checkObjectCreateCompatibility() {
84
+ if (typeof Object.create !== 'undefined')
85
+ return;
86
+
87
+ Object.create = function objectCreate(proto) {
88
+ var constructor = function objectCreateConstructor() {};
89
+ constructor.prototype = proto;
90
+ return new constructor();
91
+ };
92
+ })();
93
+
94
+ // Object.defineProperty() ?
95
+ (function checkObjectDefinePropertyCompatibility() {
96
+ if (typeof Object.defineProperty !== 'undefined') {
97
+ // some browsers (e.g. safari) cannot use defineProperty() on DOM objects
98
+ // and thus the native version is not sufficient
99
+ var definePropertyPossible = true;
100
+ try {
101
+ Object.defineProperty(new Image(), 'id', { value: 'test' });
102
+ } catch (e) {
103
+ definePropertyPossible = false;
104
+ }
105
+ if (definePropertyPossible) return;
106
+ }
107
+
108
+ Object.defineProperty = function objectDefineProperty(obj, name, def) {
109
+ delete obj[name];
110
+ if ('get' in def)
111
+ obj.__defineGetter__(name, def['get']);
112
+ if ('set' in def)
113
+ obj.__defineSetter__(name, def['set']);
114
+ if ('value' in def) {
115
+ obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
116
+ this.__defineGetter__(name, function objectDefinePropertyGetter() {
117
+ return value;
118
+ });
119
+ return value;
120
+ });
121
+ obj[name] = def.value;
122
+ }
123
+ };
124
+ })();
125
+
126
+ // Object.keys() ?
127
+ (function checkObjectKeysCompatibility() {
128
+ if (typeof Object.keys !== 'undefined')
129
+ return;
130
+
131
+ Object.keys = function objectKeys(obj) {
132
+ var result = [];
133
+ for (var i in obj) {
134
+ if (obj.hasOwnProperty(i))
135
+ result.push(i);
136
+ }
137
+ return result;
138
+ };
139
+ })();
140
+
141
+ // No readAsArrayBuffer ?
142
+ (function checkFileReaderReadAsArrayBuffer() {
143
+ if (typeof FileReader === 'undefined')
144
+ return; // FileReader is not implemented
145
+ var frPrototype = FileReader.prototype;
146
+ // Older versions of Firefox might not have readAsArrayBuffer
147
+ if ('readAsArrayBuffer' in frPrototype)
148
+ return; // readAsArrayBuffer is implemented
149
+ Object.defineProperty(frPrototype, 'readAsArrayBuffer', {
150
+ value: function fileReaderReadAsArrayBuffer(blob) {
151
+ var fileReader = new FileReader();
152
+ var originalReader = this;
153
+ fileReader.onload = function fileReaderOnload(evt) {
154
+ var data = evt.target.result;
155
+ var buffer = new ArrayBuffer(data.length);
156
+ var uint8Array = new Uint8Array(buffer);
157
+
158
+ for (var i = 0, ii = data.length; i < ii; i++)
159
+ uint8Array[i] = data.charCodeAt(i);
160
+
161
+ Object.defineProperty(originalReader, 'result', {
162
+ value: buffer,
163
+ enumerable: true,
164
+ writable: false,
165
+ configurable: true
166
+ });
167
+
168
+ var event = document.createEvent('HTMLEvents');
169
+ event.initEvent('load', false, false);
170
+ originalReader.dispatchEvent(event);
171
+ };
172
+ fileReader.readAsBinaryString(blob);
173
+ }
174
+ });
175
+ })();
176
+
177
+ // No XMLHttpRequest.response ?
178
+ (function checkXMLHttpRequestResponseCompatibility() {
179
+ var xhrPrototype = XMLHttpRequest.prototype;
180
+ if (!('overrideMimeType' in xhrPrototype)) {
181
+ // IE10 might have response, but not overrideMimeType
182
+ Object.defineProperty(xhrPrototype, 'overrideMimeType', {
183
+ value: function xmlHttpRequestOverrideMimeType(mimeType) {}
184
+ });
185
+ }
186
+ if ('response' in xhrPrototype ||
187
+ 'mozResponseArrayBuffer' in xhrPrototype ||
188
+ 'mozResponse' in xhrPrototype ||
189
+ 'responseArrayBuffer' in xhrPrototype)
190
+ return;
191
+ // IE9 ?
192
+ if (typeof VBArray !== 'undefined') {
193
+ Object.defineProperty(xhrPrototype, 'response', {
194
+ get: function xmlHttpRequestResponseGet() {
195
+ return new Uint8Array(new VBArray(this.responseBody).toArray());
196
+ }
197
+ });
198
+ return;
199
+ }
200
+
201
+ // other browsers
202
+ function responseTypeSetter() {
203
+ // will be only called to set "arraybuffer"
204
+ this.overrideMimeType('text/plain; charset=x-user-defined');
205
+ }
206
+ if (typeof xhrPrototype.overrideMimeType === 'function') {
207
+ Object.defineProperty(xhrPrototype, 'responseType',
208
+ { set: responseTypeSetter });
209
+ }
210
+ function responseGetter() {
211
+ var text = this.responseText;
212
+ var i, n = text.length;
213
+ var result = new Uint8Array(n);
214
+ for (i = 0; i < n; ++i)
215
+ result[i] = text.charCodeAt(i) & 0xFF;
216
+ return result;
217
+ }
218
+ Object.defineProperty(xhrPrototype, 'response', { get: responseGetter });
219
+ })();
220
+
221
+ // window.btoa (base64 encode function) ?
222
+ (function checkWindowBtoaCompatibility() {
223
+ if ('btoa' in window)
224
+ return;
225
+
226
+ var digits =
227
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
228
+
229
+ window.btoa = function windowBtoa(chars) {
230
+ var buffer = '';
231
+ var i, n;
232
+ for (i = 0, n = chars.length; i < n; i += 3) {
233
+ var b1 = chars.charCodeAt(i) & 0xFF;
234
+ var b2 = chars.charCodeAt(i + 1) & 0xFF;
235
+ var b3 = chars.charCodeAt(i + 2) & 0xFF;
236
+ var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
237
+ var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
238
+ var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
239
+ buffer += (digits.charAt(d1) + digits.charAt(d2) +
240
+ digits.charAt(d3) + digits.charAt(d4));
241
+ }
242
+ return buffer;
243
+ };
244
+ })();
245
+
246
+ // Function.prototype.bind ?
247
+ (function checkFunctionPrototypeBindCompatibility() {
248
+ if (typeof Function.prototype.bind !== 'undefined')
249
+ return;
250
+
251
+ Function.prototype.bind = function functionPrototypeBind(obj) {
252
+ var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
253
+ var bound = function functionPrototypeBindBound() {
254
+ var args = Array.prototype.concat.apply(headArgs, arguments);
255
+ return fn.apply(obj, args);
256
+ };
257
+ return bound;
258
+ };
259
+ })();
260
+
261
+ // IE9/10 text/html data URI
262
+ (function checkDataURICompatibility() {
263
+ if (!('documentMode' in document) ||
264
+ document.documentMode !== 9 && document.documentMode !== 10)
265
+ return;
266
+ // overriding the src property
267
+ var originalSrcDescriptor = Object.getOwnPropertyDescriptor(
268
+ HTMLIFrameElement.prototype, 'src');
269
+ Object.defineProperty(HTMLIFrameElement.prototype, 'src', {
270
+ get: function htmlIFrameElementPrototypeSrcGet() { return this.$src; },
271
+ set: function htmlIFrameElementPrototypeSrcSet(src) {
272
+ this.$src = src;
273
+ if (src.substr(0, 14) != 'data:text/html') {
274
+ originalSrcDescriptor.set.call(this, src);
275
+ return;
276
+ }
277
+ // for text/html, using blank document and then
278
+ // document's open, write, and close operations
279
+ originalSrcDescriptor.set.call(this, 'about:blank');
280
+ setTimeout((function htmlIFrameElementPrototypeSrcOpenWriteClose() {
281
+ var doc = this.contentDocument;
282
+ doc.open('text/html');
283
+ doc.write(src.substr(src.indexOf(',') + 1));
284
+ doc.close();
285
+ }).bind(this), 0);
286
+ },
287
+ enumerable: true
288
+ });
289
+ })();
290
+
291
+ // HTMLElement dataset property
292
+ (function checkDatasetProperty() {
293
+ var div = document.createElement('div');
294
+ if ('dataset' in div)
295
+ return; // dataset property exists
296
+
297
+ Object.defineProperty(HTMLElement.prototype, 'dataset', {
298
+ get: function() {
299
+ if (this._dataset)
300
+ return this._dataset;
301
+
302
+ var dataset = {};
303
+ for (var j = 0, jj = this.attributes.length; j < jj; j++) {
304
+ var attribute = this.attributes[j];
305
+ if (attribute.name.substring(0, 5) != 'data-')
306
+ continue;
307
+ var key = attribute.name.substring(5).replace(/\-([a-z])/g,
308
+ function(all, ch) { return ch.toUpperCase(); });
309
+ dataset[key] = attribute.value;
310
+ }
311
+
312
+ Object.defineProperty(this, '_dataset', {
313
+ value: dataset,
314
+ writable: false,
315
+ enumerable: false
316
+ });
317
+ return dataset;
318
+ },
319
+ enumerable: true
320
+ });
321
+ })();
322
+
323
+ // HTMLElement classList property
324
+ (function checkClassListProperty() {
325
+ var div = document.createElement('div');
326
+ if ('classList' in div)
327
+ return; // classList property exists
328
+
329
+ function changeList(element, itemName, add, remove) {
330
+ var s = element.className || '';
331
+ var list = s.split(/\s+/g);
332
+ if (list[0] == '') list.shift();
333
+ var index = list.indexOf(itemName);
334
+ if (index < 0 && add)
335
+ list.push(itemName);
336
+ if (index >= 0 && remove)
337
+ list.splice(index, 1);
338
+ element.className = list.join(' ');
339
+ }
340
+
341
+ var classListPrototype = {
342
+ add: function(name) {
343
+ changeList(this.element, name, true, false);
344
+ },
345
+ remove: function(name) {
346
+ changeList(this.element, name, false, true);
347
+ },
348
+ toggle: function(name) {
349
+ changeList(this.element, name, true, true);
350
+ }
351
+ };
352
+
353
+ Object.defineProperty(HTMLElement.prototype, 'classList', {
354
+ get: function() {
355
+ if (this._classList)
356
+ return this._classList;
357
+
358
+ var classList = Object.create(classListPrototype, {
359
+ element: {
360
+ value: this,
361
+ writable: false,
362
+ enumerable: true
363
+ }
364
+ });
365
+ Object.defineProperty(this, '_classList', {
366
+ value: classList,
367
+ writable: false,
368
+ enumerable: false
369
+ });
370
+ return classList;
371
+ },
372
+ enumerable: true
373
+ });
374
+ })();
375
+
376
+ // Check console compatability
377
+ (function checkConsoleCompatibility() {
378
+ if (typeof console == 'undefined') {
379
+ console = {log: function() {}};
380
+ }
381
+ })();
382
+
383
+ // Check onclick compatibility in Opera
384
+ (function checkOnClickCompatibility() {
385
+ // workaround for reported Opera bug DSK-354448:
386
+ // onclick fires on disabled buttons with opaque content
387
+ function ignoreIfTargetDisabled(event) {
388
+ if (isDisabled(event.target)) {
389
+ event.stopPropagation();
390
+ }
391
+ }
392
+ function isDisabled(node) {
393
+ return node.disabled || (node.parentNode && isDisabled(node.parentNode));
394
+ }
395
+ if (navigator.userAgent.indexOf('Opera') != -1) {
396
+ // use browser detection since we cannot feature-check this bug
397
+ document.addEventListener('click', ignoreIfTargetDisabled, true);
398
+ }
399
+ })();
400
+
401
+ // Checks if navigator.language is supported
402
+ (function checkNavigatorLanguage() {
403
+ if ('language' in navigator)
404
+ return;
405
+ Object.defineProperty(navigator, 'language', {
406
+ get: function navigatorLanguage() {
407
+ var language = navigator.userLanguage || 'en-US';
408
+ return language.substring(0, 2).toLowerCase() +
409
+ language.substring(2).toUpperCase();
410
+ },
411
+ enumerable: true
412
+ });
413
+ })();