Sorry, but the page you were trying to view does not exist.
146 |
It looks like this was the result of either:
147 |
148 |
a mistyped address
149 |
an out-of-date link
150 |
151 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
4 |
5 | // Project configuration.
6 | grunt.initConfig({
7 | pkg: grunt.file.readJSON('package.json'),
8 |
9 | lint: {
10 | all: ['grunt.js', 'js/debug/*.js']
11 | },
12 | jshint: {
13 | options: {
14 | browser: true
15 | }
16 | },
17 | concat: {
18 | dist: {
19 | src: ['js/debug/license.txt',
20 | 'js/dev/deeptissue.js',
21 | 'js/dev/deeptissue.move.js',
22 | 'js/dev/deeptissue.tap.js',
23 | 'js/dev/deeptissue.rotate.js',
24 | 'js/dev/deeptissue.scale.js'
25 | ],
26 | dest: 'js/deep-tissue.js',
27 | separator: ';'
28 | },
29 | license: {
30 | src: ['js/debug/license.txt',
31 | 'js/deep-tissue.min.js'
32 | ],
33 | dest: 'js/deep-tissue.min.js',
34 | separator: ';'
35 | }
36 |
37 | },
38 | uglify: {
39 | // options: {
40 | // banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
41 | //'<%= grunt.template.today("yyyy-mm-dd") %> */'
42 | // },
43 |
44 | dist: {
45 | src: ['js/dev/deeptissue.js',
46 | 'js/dev/deeptissue.move.js',
47 | 'js/dev/deeptissue.swipejs',
48 | 'js/dev/deeptissue.tap.js',
49 | 'js/dev/deeptissue.rotate.js',
50 | 'js/dev/deeptissue.scale.js'
51 | ],
52 | dest: 'js/deep-tissue.min.js'
53 | }
54 | }
55 | });
56 |
57 | // Default task.
58 | grunt.registerTask('default', ['uglify', 'concat']);
59 |
60 | };
--------------------------------------------------------------------------------
/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 2015 Love2Dev
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 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DeepTissue",
3 | "version": "0.0.5",
4 | "main": "js/deep-tissue.min.js"
5 | }
--------------------------------------------------------------------------------
/css/qunit.css:
--------------------------------------------------------------------------------
1 | /**
2 | * QUnit v1.10.0pre - A JavaScript Unit Testing Framework
3 | *
4 | * http://qunitjs.com
5 | *
6 | * Copyright 2012 jQuery Foundation and other contributors
7 | * Dual licensed under the MIT or GPL Version 2 licenses.
8 | * http://jquery.org/license
9 | */
10 |
11 | /** Font Family and Sizes */
12 |
13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
15 | }
16 |
17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
18 | #qunit-tests { font-size: smaller; }
19 |
20 |
21 | /** Resets */
22 |
23 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
24 | margin: 0;
25 | padding: 0;
26 | }
27 |
28 |
29 | /** Header */
30 |
31 | #qunit-header {
32 | padding: 0.5em 0 0.5em 1em;
33 |
34 | color: #8699a4;
35 | background-color: #0d3349;
36 |
37 | font-size: 1.5em;
38 | line-height: 1em;
39 | font-weight: normal;
40 |
41 | border-radius: 5px 5px 0 0;
42 | -moz-border-radius: 5px 5px 0 0;
43 | -webkit-border-top-right-radius: 5px;
44 | -webkit-border-top-left-radius: 5px;
45 | }
46 |
47 | #qunit-header a {
48 | text-decoration: none;
49 | color: #c2ccd1;
50 | }
51 |
52 | #qunit-header a:hover,
53 | #qunit-header a:focus {
54 | color: #fff;
55 | }
56 |
57 | #qunit-testrunner-toolbar label {
58 | display: inline-block;
59 | padding: 0 .5em 0 .1em;
60 | }
61 |
62 | #qunit-banner {
63 | height: 5px;
64 | }
65 |
66 | #qunit-testrunner-toolbar {
67 | padding: 0.5em 0 0.5em 2em;
68 | color: #5E740B;
69 | background-color: #eee;
70 | overflow: hidden;
71 | }
72 |
73 | #qunit-userAgent {
74 | padding: 0.5em 0 0.5em 2.5em;
75 | background-color: #2b81af;
76 | color: #fff;
77 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
78 | }
79 |
80 | #qunit-modulefilter-container {
81 | float: right;
82 | }
83 |
84 | /** Tests: Pass/Fail */
85 |
86 | #qunit-tests {
87 | list-style-position: inside;
88 | }
89 |
90 | #qunit-tests li {
91 | padding: 0.4em 0.5em 0.4em 2.5em;
92 | border-bottom: 1px solid #fff;
93 | list-style-position: inside;
94 | }
95 |
96 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
97 | display: none;
98 | }
99 |
100 | #qunit-tests li strong {
101 | cursor: pointer;
102 | }
103 |
104 | #qunit-tests li a {
105 | padding: 0.5em;
106 | color: #c2ccd1;
107 | text-decoration: none;
108 | }
109 | #qunit-tests li a:hover,
110 | #qunit-tests li a:focus {
111 | color: #000;
112 | }
113 |
114 | #qunit-tests ol {
115 | margin-top: 0.5em;
116 | padding: 0.5em;
117 |
118 | background-color: #fff;
119 |
120 | border-radius: 5px;
121 | -moz-border-radius: 5px;
122 | -webkit-border-radius: 5px;
123 | }
124 |
125 | #qunit-tests table {
126 | border-collapse: collapse;
127 | margin-top: .2em;
128 | }
129 |
130 | #qunit-tests th {
131 | text-align: right;
132 | vertical-align: top;
133 | padding: 0 .5em 0 0;
134 | }
135 |
136 | #qunit-tests td {
137 | vertical-align: top;
138 | }
139 |
140 | #qunit-tests pre {
141 | margin: 0;
142 | white-space: pre-wrap;
143 | word-wrap: break-word;
144 | }
145 |
146 | #qunit-tests del {
147 | background-color: #e0f2be;
148 | color: #374e0c;
149 | text-decoration: none;
150 | }
151 |
152 | #qunit-tests ins {
153 | background-color: #ffcaca;
154 | color: #500;
155 | text-decoration: none;
156 | }
157 |
158 | /*** Test Counts */
159 |
160 | #qunit-tests b.counts { color: black; }
161 | #qunit-tests b.passed { color: #5E740B; }
162 | #qunit-tests b.failed { color: #710909; }
163 |
164 | #qunit-tests li li {
165 | padding: 5px;
166 | background-color: #fff;
167 | border-bottom: none;
168 | list-style-position: inside;
169 | }
170 |
171 | /*** Passing Styles */
172 |
173 | #qunit-tests li li.pass {
174 | color: #3c510c;
175 | background-color: #fff;
176 | border-left: 10px solid #C6E746;
177 | }
178 |
179 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
180 | #qunit-tests .pass .test-name { color: #366097; }
181 |
182 | #qunit-tests .pass .test-actual,
183 | #qunit-tests .pass .test-expected { color: #999999; }
184 |
185 | #qunit-banner.qunit-pass { background-color: #C6E746; }
186 |
187 | /*** Failing Styles */
188 |
189 | #qunit-tests li li.fail {
190 | color: #710909;
191 | background-color: #fff;
192 | border-left: 10px solid #EE5757;
193 | white-space: pre;
194 | }
195 |
196 | #qunit-tests > li:last-child {
197 | border-radius: 0 0 5px 5px;
198 | -moz-border-radius: 0 0 5px 5px;
199 | -webkit-border-bottom-right-radius: 5px;
200 | -webkit-border-bottom-left-radius: 5px;
201 | }
202 |
203 | #qunit-tests .fail { color: #000000; background-color: #EE5757; }
204 | #qunit-tests .fail .test-name,
205 | #qunit-tests .fail .module-name { color: #000000; }
206 |
207 | #qunit-tests .fail .test-actual { color: #EE5757; }
208 | #qunit-tests .fail .test-expected { color: green; }
209 |
210 | #qunit-banner.qunit-fail { background-color: #EE5757; }
211 |
212 |
213 | /** Result */
214 |
215 | #qunit-testresult {
216 | padding: 0.5em 0.5em 0.5em 2.5em;
217 |
218 | color: #2b81af;
219 | background-color: #D2E0E6;
220 |
221 | border-bottom: 1px solid white;
222 | }
223 | #qunit-testresult .module-name {
224 | font-weight: bold;
225 | }
226 |
227 | /** Fixture */
228 |
229 | #qunit-fixture {
230 | position: absolute;
231 | top: -10000px;
232 | left: -10000px;
233 | width: 1000px;
234 | height: 1000px;
235 | }
236 |
--------------------------------------------------------------------------------
/css/site.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | cursor: default;
3 | height: 100%;
4 | -ms-scroll-translation: vertical-to-horizontal;
5 | -ms-user-select: none;
6 | -webkit-user-select: none;
7 | -moz-user-select: none;
8 | user-select: none;
9 | -ms-touch-action: none;
10 | }
11 |
12 | html {
13 | -webkit-text-size-adjust: none; /* Prevent font scaling in landscape */
14 | }
15 |
16 | body {
17 | -ms-content-zooming: none;
18 | font-family: 'Segoe UI', 'Segoe WP', sans-serif;
19 | font-size: 11pt;
20 | letter-spacing: 0.02em;
21 | margin: 0px 20px 20px 20px;
22 | padding: 0 0 25px 0;
23 | background-color: #2e2d2d;
24 | color: #f5efef;
25 | overflow-x: hidden;
26 | }
27 |
28 | nav
29 | {
30 | width: 600px;
31 | margin: 20px auto;
32 | }
33 |
34 | nav > a {
35 | margin: 5px 15px 20px 15px;
36 | padding: 5px 10px;
37 | text-decoration: none;
38 | text-align: center;
39 | background-color: #0094ff;
40 | color: #fff;
41 | font-size: 1.25em;
42 | font-weight: bold;
43 | }
44 |
45 | .ribbon {
46 | background-color: #f5efef;
47 | overflow: hidden;
48 | /* top left corner */
49 | position: absolute;
50 | right: -3em;
51 | top: 2.5em;
52 | /* 45 deg cw rotation */
53 | -moz-transform: rotate(45deg);
54 | -webkit-transform: rotate(45deg);
55 | transform: rotate(45deg);
56 | /* shadow */
57 | -moz-box-shadow: 0 0 1em #888;
58 | -webkit-box-shadow: 0 0 1em #888;
59 | box-shadow: 0 0 1em #888;
60 | }
61 |
62 | .ribbon a {
63 | border: 1px solid #faa;
64 | color: #0094ff;
65 | display: block;
66 | font: bold 81.25% 'Helvetiva Neue', Helvetica, Arial, sans-serif;
67 | margin: 0.05em 0 0.075em 0;
68 | padding: 0.5em 3.5em;
69 | text-align: center;
70 | text-decoration: none;
71 | /* shadow */
72 | text-shadow: 0 0 0.5em #2683c7;
73 | }
74 |
75 | .main-content {
76 | margin: 20px 10px 20px 40px;
77 | }
78 |
79 | .touch-area {
80 | background-color: #0094ff;
81 | color: #2e2d2d;
82 | width: 200px;
83 | height: 200px;
84 | display: block;
85 | margin: 24px auto;
86 | float: left;
87 | overflow: hidden;
88 | -ms-touch-action: none;
89 | text-align: center;
90 | margin: 15px;
91 | border: solid 1px #f5efef;
92 | line-height: 200px;
93 | color: #f5efef;
94 | font-size: 1.5em;
95 |
96 | }
97 |
98 | .touch-log {
99 | background-color: #f5efef;
100 | color: #2e2d2d;
101 | width: 300px;
102 | height: 100px;
103 | display: block;
104 | margin: 24px;
105 | clear: both;
106 | }
107 |
108 | a.no-decor {
109 | text-decoration: none;
110 | color: #fff;
111 | }
112 |
113 | a.clone {
114 | font-size: 1.2em;
115 | color: #fff;
116 | font-weight: bold;
117 | padding: 5px 10px;
118 | background-color: #0094ff;
119 | }
120 |
121 | .site-logo
122 | {
123 | float: left;
124 | border: none;
125 | }
126 |
127 | a.active
128 | {
129 | border-bottom: solid 3px #fff;
130 | }
131 |
132 | .center-item
133 | {
134 | float: none;
135 | margin: 10px auto;
136 | }
137 |
138 |
139 | p{
140 | font-family: Calibri Verdana;
141 | }
--------------------------------------------------------------------------------
/customteventtest.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Deep Tissue Real Tests
6 |
7 |
8 |
61 |
62 |
63 |
64 |
Move Test
65 |
66 |
67 |
68 |
69 |
blah blah bal
70 |
blah blah bal
71 |
blah blah bal
72 |
blah blah bal
73 |
blah blah bal
74 |
blah blah bal
75 |
blah blah bal
76 |
blah blah bal
77 |
78 |
79 |
80 | Log Goes Here
81 |
82 |
83 |
84 |
85 |
86 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/deeptissuejs.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.30723.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "deeptissuejs", "http://localhost:59409", "{6F90BA92-7562-4B2E-90B2-1CD7BA6B70AA}"
7 | ProjectSection(WebsiteProperties) = preProject
8 | UseIISExpress = "true"
9 | TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
10 | Debug.AspNetCompiler.VirtualPath = "/localhost_59409"
11 | Debug.AspNetCompiler.PhysicalPath = "..\deeptissuejs\"
12 | Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_59409\"
13 | Debug.AspNetCompiler.Updateable = "true"
14 | Debug.AspNetCompiler.ForceOverwrite = "true"
15 | Debug.AspNetCompiler.FixedNames = "false"
16 | Debug.AspNetCompiler.Debug = "True"
17 | Release.AspNetCompiler.VirtualPath = "/localhost_59409"
18 | Release.AspNetCompiler.PhysicalPath = "..\deeptissuejs\"
19 | Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_59409\"
20 | Release.AspNetCompiler.Updateable = "true"
21 | Release.AspNetCompiler.ForceOverwrite = "true"
22 | Release.AspNetCompiler.FixedNames = "false"
23 | Release.AspNetCompiler.Debug = "False"
24 | SlnRelativePath = "..\deeptissuejs\"
25 | EndProjectSection
26 | EndProject
27 | Global
28 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
29 | Debug|Any CPU = Debug|Any CPU
30 | EndGlobalSection
31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
32 | {6F90BA92-7562-4B2E-90B2-1CD7BA6B70AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {6F90BA92-7562-4B2E-90B2-1CD7BA6B70AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | EndGlobal
39 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/)
2 |
3 | # Deeptissue documentation:
4 |
5 | * [Basic Example](basic.md) — Quick Example.
6 | * [Tap Example](tap.md) — Tap Methods Example.
7 | * [Move Example](move.md) — Move Methods Example.
8 | * [Swipe Example](swipe.md) — Swipe Methods Example.
9 | * [Rotate Example](rotate.md) — Rotate Example.
10 | * [Scale Example](scale.md) — Scale Example.
11 | * [FAQ](faq.md) — Frequently asked questions, along with their answers.
12 |
13 |
14 | *** Note I am just writing this stuff as I think of it. I apologize for
15 | typos, misspellings, etc.
16 |
17 |
--------------------------------------------------------------------------------
/doc/basic.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/) | [Documentation
2 | table of contents](README.md)
3 |
4 | # Basic Information
5 |
6 | deeptissue is designed to be simple, extensible with no 3rd party library
7 | dependence. To create a new deeptissue object you simply need to provide a
8 | reference to either a DOM node or nodeList. Basically if you use
9 | document.getElementById, .querySelector, .querySelectorAll, etc to retrieve
10 | a reference to DOM element(s) it will work.
11 |
12 | With that you need to have at least one element to act upon:
13 |
14 | Single Tap
15 |
16 | In this example I am going to use the 'sgl-tap' CSS class as a selector.
17 |
18 | var dt = deeptissue(document.querySelectorAll(".sgl-tap"));
19 |
20 | In this example I used the document.querySelectorAll, but I could have
21 | just as easily used .querySelector or .getElementsByClassName, deeptissue
22 | will not care.
23 |
24 | Now that you have a deeptissue object, dt, you can now call the
25 | touch abstraction methods. Each method has a single parameter, a callback
26 | method.
27 |
28 | dt.tap(function (evt) {
29 |
30 | //you wonderful action driver goes here
31 |
32 | });
33 |
34 | That is pretty much it. I wanted to make it simple.
35 |
36 | Now for a little fancy.
37 |
38 | You can actually pass in a 2nd, optional parameter, settings, to the deeptissue
39 | constructor. This object should contain any default settings overrides
40 | you want to make so the library's behavior is modified. Because JavaScript
41 | is very flexible you can choose what properties to modify and ignore others.
42 | Hek if you want to add a new property more power to you, I don't have a mechanism
43 | in place to use them, but hey its your app afterall :)
44 |
45 | var dt = deeptissue(document.querySelectorAll(".sgl-tap"),
46 | {
47 | swipeRightThreshold: 5, //wow this is a wuick trigger!
48 | swipeLeftThreshold: -5,
49 | swipeUpThreshold: 5,
50 | swipeDownThreshold: 5,
51 | });
52 |
53 |
54 | These are the default settings values. There are a few properties that are not
55 | currently being used. They will either go away or become something relevant in
56 | the coming days.
57 |
58 | settings: {
59 | allowPageScroll: true,
60 | logging: false,
61 | swipeRightThreshold: 25,
62 | swipeLeftThreshold: -25,
63 | swipeUpThreshold: 25,
64 | swipeDownThreshold: 25,
65 | moveThreshold: 0,
66 | rotateThreshold: 0,
67 | scaleThreshold: 0,
68 |
69 | doubleTapThreshold: 25,
70 |
71 | //magic strings be gone!
72 | tapIndicator: "data-tap",
73 | tapStart: "data-tap-start",
74 | tapEnded: "data-tap-end",
75 |
76 | doubleTapIndicator: "data-dbltap",
77 | doubleTapStart: "data-dbltap-start",
78 | doubleTapEnded: "data-dbltap-end",
79 |
80 |
81 | rotateIndicator: "data-rotate",
82 | rotateEnded: "data-rotate-ended",
83 | rotateInitial: "data-rotate-initial",
84 |
85 | scaleIndicator: "data-scale",
86 | scaleEnded: "data-scale-ended",
87 | scaleInitial: "data-scale-initial",
88 |
89 | moveIndicator: "data-move",
90 | moveTouchEnded: "data-move-touch-ended",
91 | moveTouchInitial: "data-move-touch-initial",
92 |
93 | swipeRight: "data-swiperight",
94 | swipeRightInit: "data-swiperight-init",
95 | swipeRightEnd: "data-swiperight-end",
96 |
97 | swipeLeft: "data-swipeleft",
98 | swipeLeftInit: "data-swipeLeft-init",
99 | swipeLeftEnd: "data-swipeleft-end",
100 |
101 | swipeUp: "data-swipeup",
102 | swipeUpInit: "data-swipeup-init",
103 | swipeUpEnd: "data-swipeup-end",
104 |
105 | swipeDown: "data-swipedown",
106 | swipeDownInit: "data-swipedown-init",
107 | swipeDownEnd: "data-swipedown-end",
108 |
109 | horizontalIndicator: "data-move-horizontal",
110 | horizontalTouchInit: "data-horizontal-touch-initial",
111 | horizontalTouchEnd: "data-horizontal-touch-ended",
112 |
113 | verticalIndicator: "data-move-vertical",
114 | verticalTouchInit: "data-vertical-touch-initial",
115 | verticalTouchEnd: "data-vertical-touch-ended"
116 |
117 | }
--------------------------------------------------------------------------------
/doc/faq.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/) | [Documentation
2 | table of contents](README.md)
3 |
4 | # Frequently asked questions
5 |
6 |
7 | No one has asked me anything yet :>s
--------------------------------------------------------------------------------
/doc/move.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/) | [Documentation
2 | table of contents](README.md)
3 |
4 | # Move Method Examples
5 |
6 | These are examples for the Move, Vertical Move and Horizontal Move functionality.
7 | The methods will execute when a user does the desired action. Each method
8 | has one parameter, an optional callback method. While you do not have
9 | to specify a callback you really should, otherwise this is just wasted code.
10 |
11 | Verified on: IE 9+, Chrome, FireFox, Mobile Safari
12 |
13 | #Move
14 |
15 | Like all the deeptissue methods you need a node or nodeList reference. Here is an
16 | example Section element for this example:
17 |
18 |
19 |
Move
20 |
21 |
22 | To create a new deeptissue object you need to pass a reference to the targeted
23 | elements, which you would select using one of the document.querySelectorAll sort
24 | of methods, like this:
25 |
26 | var mvt = document.querySelectorAll(".move-target"),
27 | dt = deeptissue(mvt);
28 |
29 | Now all you need to do is execute the move method, passing a callback to execute when the
30 | user moves the target element.
31 |
32 | dt.move(function (evt, m) {
33 |
34 | el.textContent = "move " +
35 | evt.translationX + "px " +
36 | evt.translationY + "px\n" +
37 | el.textContent;
38 |
39 | });
40 |
41 | Note, for now the library assumes you want to move the element so it does just that.
42 | Basically it will follow your finger or mouse around the screen.
43 |
44 | Vertical and Horizontal moves work exactly the same. The only difference is they have
45 | 'govenors' in place to only allow movement either up and down or left and right.
46 |
47 |
--------------------------------------------------------------------------------
/doc/rotate.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/) | [Documentation
2 | table of contents](README.md)
3 |
4 | # Rotate Method Examples
5 |
6 | This is an example for the Rotate functionality. The methods will execute
7 | when a user does the desired action, which is place two fingers on the screen
8 | and twist their hand. Like the other methods there is one parameter, a callback.
9 |
10 | Note this will only work on IE 10 with touch and mobile safari. I do not have it
11 | working for Android/Chrome etc since they do not support gestures. Since it looks
12 | like Chrome will soon support the MSPointer API (lets hope) I may not bother with
13 | Android support.
14 |
15 | #Rotate
16 |
17 | Like all the deeptissue methods you need a node or nodeList reference. Here is an
18 | example Section element for this example:
19 |
20 |
21 |
22 | To create a new deeptissue object you need to pass a reference to the targeted
23 | elements, which you would select using one of the document.querySelectorAll sort
24 | of methods, like this:
25 |
26 | var tl = document.querySelector(".touch-log"),
27 | rt = deeptissue(document.querySelectorAll(".rotate-target"));
28 |
29 | Now all you need to do is execute the move method, passing a callback to execute when the
30 | user moves the target element.
31 |
32 | rt.rotate(function (evt, m) {
33 |
34 | tl.textContent = "rotating " +
35 | evt.rotation + "\n" +
36 | tl.textContent;
37 |
38 | evt.target.style.transform = m.rotate(evt.rotation * 180 / Math.PI); // Apply Rotation
39 |
40 | });
41 |
42 | Note, for now the library assumes you want to rotate the element so it does just that.
43 | Basically it will follow your finger's movement on the screen.
44 |
--------------------------------------------------------------------------------
/doc/scale.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/) | [Documentation
2 | table of contents](README.md)
3 |
4 | # Scale Method Examples
5 |
6 | This is an example for the Scale functionality. The methods will execute
7 | when a user does the desired action, which is place two fingers on the screen
8 | and twist their hand. Like the other methods there is one parameter, a callback.
9 |
10 | Note this will only work on IE 10 with touch and mobile safari. I do not have it
11 | working for Android/Chrome etc since they do not support gestures. Since it looks
12 | like Chrome will soon support the MSPointer API (lets hope) I may not bother with
13 | Android support.
14 |
15 | #Scale
16 |
17 | Like all the deeptissue methods you need a node or nodeList reference. Here is an
18 | example Section element for this example:
19 |
20 |
21 |
22 | To create a new deeptissue object you need to pass a reference to the targeted
23 | elements, which you would select using one of the document.querySelectorAll sort
24 | of methods, like this:
25 |
26 | var tl = document.querySelector(".touch-log"),
27 | st = deeptissue(document.querySelectorAll(".scale-target"));
28 |
29 | Now all you need to do is execute the move method, passing a callback to execute when the
30 | user moves the target element.
31 |
32 | st.scale(function (evt, m) {
33 |
34 | tl.textContent = "scaling " +
35 | evt.scale + "\n" +
36 | tl.textContent;
37 |
38 | evt.target.style.transform = m.scale(evt.scale); // Apply Scale
39 |
40 | });
41 |
42 | Note, for now the library assumes you want to scale the element so it does just that.
43 | Basically it will follow your finger's movement on the screen.
44 |
--------------------------------------------------------------------------------
/doc/swipe.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/) | [Documentation
2 | table of contents](README.md)
3 |
4 | # Swipe Method Examples
5 |
6 | These are examples for the Swipe Right, Left, Up and Down functionality.
7 | The methods will execute when a user does the desired action. Each method
8 | has one parameter, an optional callback method. While you do not have
9 | to specify a callback you really should, otherwise this is just wasted code.
10 |
11 | Verified on: IE 9+, Chrome, FireFox, Mobile Safari
12 |
13 | #SwipeRight, SwipeLeft, SwipeUp, SwipeDown
14 |
15 | Unlke the other examples, this time I am going to show the chaining capabilities for
16 | each of the deeptissue action methods. Again they will apply the desired functionality
17 | to the target element.
18 |
19 |
20 |
21 | Now select the element and create a deeptissue object.
22 |
23 | var dt = deeptissue(document.querySelectorAll((".touch-area")));
24 |
25 | dt.swipeRight(function (evt, m, translate) {
26 |
27 | //do something here
28 |
29 | })
30 |
31 | .swipeLeft(function (evt, m, translate) {
32 |
33 | //do something here
34 |
35 | })
36 |
37 | .swipeDown(function (evt, m, translate) {
38 |
39 | //do something here
40 |
41 | })
42 |
43 | .swipeUp(function (evt, m, translate) {
44 |
45 | //do something here
46 |
47 | });
48 |
49 | Look for some changes to these methods. Right now they are firing every time a move event
50 | fires after the threshold is satisfied. I think I will change it to a single event exection.
51 | Also know you can adjust the distance threshold for each of the directions. The default
52 | value is 25 pixels.
--------------------------------------------------------------------------------
/doc/tap.md:
--------------------------------------------------------------------------------
1 | [Deeptissue.js homepage](http://deeptissuejs.com/) | [Documentation
2 | table of contents](README.md)
3 |
4 | # Tap Method Examples
5 | These are examples for the Tap, Double Tap and Tap Hold functionality.
6 | The methods will execute when a user does the desired action. Each method
7 | have one parameter, an optional callback method. While you do not have
8 | to specify a callback you really should, otherwise this is just wasted code.
9 |
10 | Verified on: IE 9+, Chrome, FireFox, Mobile Safari
11 |
12 | #Tap
13 |
14 | A tap identifies when a user quickly clicks an element with the mouse or quick touch
15 | with their finger or pointer device (IE 10+). First you need to define the target
16 | element the user should tap.
17 |
18 | Single Tap
19 |
20 | To apply Deeptissue you need to pass a reference to the target element(s) to the
21 | deeptissue constructor. Note you do not need to create the deeptissue object with
22 | a new operator it is self instantiating.
23 |
24 | var dt = deeptissue(document.querySelectorAll(".sgl-tap"));
25 |
26 | Now call the tap method, passing a callback method. Here I am writing to another
27 | elemet to let me know I tapped and echoing some values to the console. You can
28 | see this in the demo pages.
29 |
30 | dt.tap(function (evt) {
31 |
32 | tl.textContent = "Single Tap\n" + tl.textContent;
33 |
34 | console.log(evt.type);
35 | console.log(evt.screenX);
36 | console.log(evt.screenY);
37 |
38 | });
39 |
40 | For doubleTap do the same thing, except call the dblTap method. You can adjust the
41 | time sensitivity by changing the doubleTapThreshold setting. The doubleTapThreshold
42 | value is in milliseconds.
43 |
44 | For Tap+Hold call the tapHold method. The tapHold functionality will either
45 | use the MSGesture for tapHold or use a timeout for other platforms.
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/docluv/deeptissuejs/2455e8f32e198939fdb2266a2616606a2ac547f3/favicon.ico
--------------------------------------------------------------------------------
/grunt.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | // Project configuration.
4 | grunt.initConfig({
5 | lint: {
6 | all: ['grunt.js', 'js/debug/*.js']
7 | },
8 | jshint: {
9 | options: {
10 | browser: true
11 | }
12 | },
13 | concat: {
14 | dist: {
15 | src: ['js/debug/license.txt',
16 | 'js/dev/deeptissue.js',
17 | 'js/dev/deeptissue.move.js',
18 | 'js/dev/deeptissue.swipejs',
19 | 'js/dev/deeptissue.tap.js',
20 | 'js/dev/deeptissue.rotate.js',
21 | 'js/dev/deeptissue.scale.js',
22 | 'js/dev/deeptissue.swipe.js'
23 | //,'js/dev/deeptissue-swipetoselect.js'
24 | ],
25 | dest: 'js/deep-tissue.js',
26 | separator: ';'
27 | },
28 | license: {
29 | src: ['js/debug/license.txt',
30 | 'js/deep-tissue.min.js'
31 | ],
32 | dest:'js/deep-tissue.min.js',
33 | separator: ';'
34 | }
35 |
36 | },
37 | min: {
38 | dist: {
39 | src: ['js/dev/deeptissue.js',
40 | 'js/dev/deeptissue.move.js',
41 | 'js/dev/deeptissue.swipejs',
42 | 'js/dev/deeptissue.tap.js',
43 | 'js/dev/deeptissue.rotate.js',
44 | 'js/dev/deeptissue.scale.js',
45 | 'js/dev/deeptissue.swipe.js'
46 | //,'js/dev/deeptissue-swipetoselect.js'
47 | ],
48 | dest: 'js/deep-tissue.min.js'
49 | }
50 | }
51 | });
52 |
53 | // Load tasks from "grunt-sample" grunt plugin installed via Npm.
54 | // grunt.loadNpmTasks('grunt-sample');
55 |
56 | // Default task.
57 | grunt.registerTask('default', 'lint min concat');
58 |
59 | };
--------------------------------------------------------------------------------
/humans.txt:
--------------------------------------------------------------------------------
1 | # humanstxt.org/
2 | # The humans responsible & technology colophon
3 |
4 | # TEAM
5 |
6 | Chris Love -- Onwer/Develloper/Bottle Washer -- @ChrisLove
7 |
8 | # THANKS
9 |
10 |
11 |
12 | # TECHNOLOGY COLOPHON
13 |
14 | HTML5, CSS3, JavaScript
15 |
--------------------------------------------------------------------------------
/ietest.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Gesture Event Firing test
6 |
19 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
Gesture Event Count:
149 |
150 |
151 |
152 | Type ScrX ScrY CliX CliY TrnX TrnY Scal Rotn Det Current Source
153 |
154 |
A Gesture Abstraction Library for both MSPointer and WebKit Touch APIs
41 |
48 |
49 |
50 |
51 |
52 |
Deeptissue.js is a helper library to abstract away the differences between the MSPointer, WebKit (Apple) Touch and Mouse event APIs. There are many JavaScript libraries publicly available that support the WebKit API and a few that help with the MSPointer API, but I found nothing that bridged the gap. So I decided I would create a library to do just that.
The library was written with no 3rd party library, like jQuery, dependencies. The library does work just fine with jQuery. In fact I will have an additional jQuery file that provides extension methods structured consistently with the way jQuery abstracts standard browser events.
56 |
57 |
In the initial release the following actions are supported:
58 |
59 |
Tap
60 |
Double Tap
61 |
Tap Hold
62 |
Move
63 |
Horizontal Move
64 |
Vertical Move
65 |
Swipe Left
66 |
Swipe Right
67 |
Swipe Up
68 |
Swipe Down
69 |
70 |
For Internet Explorer 10 and Mobile Safari these additional gestures are supported:
71 |
72 |
Rotate
73 |
Scale
74 |
75 |
In the near future I may add Android gesture support. I am sort of holding out to see if they will adopt the MSPointer model soon. If so then boom! it should work. If not then it is a lot of calculations and testing required.
76 |
I also have a list of additional gestures I hope to support in the near future:
77 |
78 |
Multi-Finger Taps
79 |
Multi-Finger Swipes
80 |
Swipe To Select
81 |
82 |
Some things to note:
83 |
84 |
I have not been able to get Rotate to work on Windows Phone. I have confirmed this is a bug in the browser and we will just have to wait for them to fix it now. It does work in Windows 8.
85 |
86 |
Unit Testing
87 |
88 |
Before you ding me for my Unit testing hear me out. I have a very small set of unit tests but will add more over time. Here is the thing, this is a UX library and its hard to AssertIsCool, AssertIsFluid, AssertIsAmazing. Sure there are some things I can test and I will. What is hard though is trying to write an entire mock and stub infrastructure to mimic both MSPointer and WebKit Touch APIs. You also need a full fledge CSSMatrix stub, etc. There is a lot of back plumbing to truly have a solid set of unit tests covering the entire set of functionality.
89 |
90 |
You also need to consider this has started as a learning curve project. There are lots of things I had to 'experience' across devices if you will. In my opinion there is not the deep documentation available for any of the APIs that would help with knowing what can and cannot be done, what to expect, etc. There is a lot of setting breakpoints, stepping through, watches, console.write's etc involved.
91 |
92 |
Instead I chose to create pages I could test different scenarios in real-life. I mean the real tests after all involve actually actions and seeing what happens.
93 |
94 |
You can visit these pages by selecting them in the header or footer navigation. Like Unit tests I will most likely add more of these pages over time. Each page will generally have one or more target test items with a log element to echo relevant values.
95 |
96 |
Documentation
97 |
98 |
You can always reference the test pages. I have also included a set of documentation files that will hopefully help you as well.
99 |
100 |
101 |
Conclusion
102 |
103 |
Please feel free to use this library. I am integrating it to my web sites and will list the as they come online, so I am dogfooding this library. I consider it early Alpha if you will because I really want to do more testing. If you have any comments or questions drop me a line, Twitter is probably the best way, @ChrisLove. My blog is ProfessionalAspNet.com. I am new to this GitHub thing so I may or may not know proper GitHub etiquette, so please forgive my missteps there.
120 |
121 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/js/deep-tissue.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Chris Love
3 |
4 | http://deeptissuejs.com
5 | https://github.com/docluv/deeptissuejs
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | 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.
12 | */
13 |
14 |
15 | !function(a,b,c){"use strict";function d(a){return document.querySelector(a)}return HTMLElement.prototype.ha=HTMLElement.prototype.hasAttribute,deeptissue=function(a,b){return new deeptissue.fn.init(a,b)},deeptissue.fn=deeptissue.prototype={constructor:deeptissue,init:function(c,d){return c?(this.node="length"in c?c:[c],this.settings=b.extend({},this.settings,d),this.support=b.buildVendorNames(),this.touchType=a.navigator.msPointerEnabled?"pointer":"ontouchstart"in a?"touch":"mouse",this.hasMouse="ontouchstart"in a&&"onmousedown"in a,this.touchStart="pointer"===this.touchType?"MSPointerDown":"touch"===this.touchType?"touchstart":"mousedown",this.touchEnd="pointer"===this.touchType?"MSPointerUp":"touch"===this.touchType?"touchend":"mouseup",this.touchOut="pointer"===this.touchType?"MSPointerOut":"touch"===this.touchType?"touchcancel":"mouseout",this.touchMove="pointer"===this.touchType?"MSPointerMove":"touch"===this.touchType?"touchmove":"mousemove",this.touchCancel="pointer"===this.touchType?"MSPointerCancel":"touch"===this.touchType?"touchcancel":"mouseout",this.hasmsGesture?this.setupMSGesture():(this.setUpTouchGestures(),this.setupTouch()),this):c},version:"0.0.5",hasMouse:"",touchType:"",touchStart:"",touchEnd:"",touchOut:"",touchMove:"",touchCancel:"",hasmsGesture:a.MSGesture,setUpTouchGestures:function(){var a=this;try{[].forEach.call(this.node,function(b){b.addEventListener("gesturestart",function(a){a.preventDefault()}),b.addEventListener("gesturechange",function(b){a.gestureChange.call(a,b)}),b.gStartScale=1,b.gStartRotation=0})}catch(b){return console.error("setUpTouchGestures is broken \r\n"+tl.textContent),!1}},setupMSGesture:function(){var a=this,b=this.settings;try{[].forEach.call(this.node,function(c){var d=new MSGesture;d&&(d.target=c,c.addEventListener("MSPointerDown",function(e){d.addPointer(e.pointerId),a.setupSwipe(e,c,b)}),c.addEventListener("MSGestureChange",function(b){a.msGestureChange.call(a,b)}),c.addEventListener("MSPointerDown",function(d){a.doDoubleTap(d,c,b)}),c.addEventListener("MSGestureEnd",function(){console.info("MSGestureEnd"),a.endGesture()}))})}catch(c){return!1}},endGesture:function(){this.swipping=!1,this.swipeX=null,this.swipeY=null},swipeRightCallback:b.noop,swipeLeftCallback:b.noop,swipeUpCallback:b.noop,swipeDownCallback:b.noop,moveCallback:b.noop,moveHorizontalCallback:b.noop,moveVerticalCallback:b.noop,rotateCallback:b.noop,scaleCallback:b.noop,tapCallback:b.noop,doubleTapCallback:b.noop,processGestureChange:function(a,b){var c=this,d=this.settings,e=a.target;e.ha(d.rotateIndicator)&&Math.abs(a.rotation)>d.rotateThreshold&&(d.autoRotate&&(e.style.transform=b.rotate(180*a.rotation/Math.PI)),this.rotateCallback(a,b)),e.ha(d.scaleIndicator)&&Math.abs(a.scale)>d.scaleThreshold&&(d.autoScale&&(e.style.transform=b.scale(a.scale)),this.scaleCallback(a,b)),e.ha(d.moveIndicator)&&(Math.abs(a.translationX)>d.moveThreshold||Math.abs(a.translationY)>d.moveThreshold)&&(d.autoMove&&(e.style.transform=b.translate(a.translationX,a.translationY,0)),this.moveCallback(a,b)),e.ha(d.horizontalIndicator)&&Math.abs(a.translationX)>d.moveThreshold&&(d.autoHorizontalMove&&(a.target.style.transform=b.translate(a.translationX,0,0)),this.moveHorizontalCallback(a,b)),e.ha(d.verticalIndicator)&&Math.abs(a.translationY)>d.moveThreshold&&(d.autoVerticalMove&&(a.target.style.transform=b.translate(0,a.translationY,0)),this.moveVerticalCallback(a,b)),c.processSwipe(e,a,d,b)},processSwipe:function(a,b,c,d){var e=this;if(d=d||{},a.ha(c.swipeRight)&&!e.swipping&&(null===e.swipeX?e.swipeX=b.clientX:a.ha(c.swipeRightInit)&&b.clientX>e.swipeX&&b.clientX-e.swipeX>c.swipeRightThreshold&&(e.swipping||(console.info("swipeRight"),e.swipping=!0,e.swipeX=null,e.swipeY=null,e.swipeRightCallback(b,d)))),a.ha(c.swipeLeft)&&!e.swipping&&(null===e.swipeX?e.swipeX=b.clientX:a.ha(c.swipeLeftInit)&&b.clientX=0?b.clientY:0;a.ha(c.swipeUpInit)&&b.clientYe.swipeY&&b.clientY-e.swipeY>c.swipeDownThreshold&&(e.swipping||(console.info("swipe Down"),e.swipping=!0,e.swipeY=null,e.swipeX=null,e.swipeDownCallback(b,d))))},swipping:!1,swipeX:null,swipeY:null,gestureChange:function(a){var b=a.target,c=this.settings;a.preventDefault(),console.info("gesture Change \r\n"+b.ha(c.rotateIndicator)+"\r\n"),b.ha(c.rotateIndicator)&&Math.abs(a.rotation)>c.rotateThreshold&&(b.style.webkitTransform="rotate("+(b.gStartRotation+a.rotation)+"deg)",this.rotateCallback(a,m)),b.ha(c.scaleIndicator)&&Math.abs(a.scale)>c.scaleThreshold&&(b.style.webkitTransform="scale("+b.gStartScale*a.scale+") ",this.scaleCallback(a,m))},msGestureChange:function(b){a.MSCSSMatrix&&this.processGestureChange(b,new MSCSSMatrix(b.target.style.transform))},calculateTranslation:function(a,b){return{translationX:b.x-a.x,translationY:b.y-a.y}},setupIndicator:function(a,b,d,e,f){var g=this,h=g.settings;a!==c&&(g[b]=a),d&&(g.settings[e]=d),[].forEach.call(g.node,function(a){a.setAttribute(h[f],"true")})},PreventDefaultManipulationAndMouseEvent:function(a){return a.preventDefault?void a.preventDefault():a.preventManipulation?void a.preventManipulation():a.preventMouseEvent?void a.preventMouseEvent():void 0},getTouchPoints:function(a){var b,c=this,d="undefined"!=typeof a.changedTouches?a.changedTouches:[a],e=d[d.length-1];return b="pointer"===c.touchType?{x:e.x,y:e.y}:"touch"===c.touchType?{x:e.pageX,y:e.pageY}:{x:a.pageX,y:a.pageY}},node:c,div:c,support:{},doDoubleTap:function(a,b,c){var d=this;b.ha(c.doubleTapIndicator)&&b.ha(c.doubleTapStart)&&(b.removeAttribute(c.doubleTapStart),clearTimeout(b.getAttribute(c.doubleTapStart)),d.doubleTapCallback(a)),b.ha(c.doubleTapIndicator)&&!b.ha(c.doubleTapStart)&&b.setAttribute(c.doubleTapStart,setTimeout(function(){b.removeAttribute(c.doubleTapStart),clearTimeout(b.getAttribute(c.doubleTapStart))},c.doubleTapThreshold))},setupSwipe:function(a,b,c){var d=this;b.ha(c.swipeRight)&&(b.removeAttribute(c.swipeRightEnd),b.ha(c.swipeRightInit)||b.setAttribute(c.swipeRightInit,JSON.stringify(d.getTouchPoints(a)))),b.ha(c.swipeLeft)&&(b.removeAttribute(c.swipeLeftEnd),b.ha(c.swipeLeftInit)||b.setAttribute(c.swipeLeftInit,JSON.stringify(d.getTouchPoints(a)))),b.ha(c.swipeUp)&&(b.removeAttribute(c.swipeUpEnd),b.ha(c.swipeUpInit)||b.setAttribute(c.swipeUpInit,JSON.stringify(d.getTouchPoints(a)))),b.ha(c.swipeDown)&&(b.removeAttribute(c.swipeDownEnd),b.ha(c.swipeDownInit)||b.setAttribute(c.swipeDownInit,JSON.stringify(d.getTouchPoints(a))))},setupTouch:function(){var a=this,b=this.settings;[].forEach.call(this.node,function(c){var d=function(d){d.preventDefault(),a.touchMoveHandler.call(a,d,c,b)},e=function(d){d.preventDefault(),a.endTouchHandler.call(a,d,c,b)},f=function(d){d.preventDefault(),a.startTouchHandler.call(a,d,c,b)};c.addEventListener(a.touchStart,f),c.addEventListener(a.touchMove,d),c.addEventListener(a.touchEnd,e),c.addEventListener(a.touchCancel,e),c.addEventListener("mouseout",e),c.addEventListener("mouseup",e),c.addEventListener(a.touchEnd,function(){console.info("touchEnd")}),c.addEventListener("mouseout",function(){console.info("mouseout")}),c.addEventListener("mouseup",function(){console.info("mouseup")}),c.addEventListener(a.touchCancel,function(){console.info("touchCancel")}),c.addEventListener(a.touchOut,function(){console.info("touchOut")}),a.hasMouse&&(c.addEventListener("mousedown",f),c.addEventListener("mousemove",d),c.addEventListener("mouseup",e))})},startTouchHandler:function(a,b,c){var d=this;c=this.settings,a.preventDefault(),console.info("touch start"),b.ha(c.moveIndicator)&&(b.removeAttribute(c.moveTouchEnded),b.ha(c.moveTouchInitial)||b.setAttribute(c.moveTouchInitial,JSON.stringify(d.getTouchPoints(a)))),b.ha(c.horizontalIndicator)&&(b.removeAttribute(c.horizontalTouchEnd),b.ha(c.horizontalTouchInit)||b.setAttribute(c.horizontalTouchInit,JSON.stringify(d.getTouchPoints(a)))),b.ha(c.verticalIndicator)&&(b.removeAttribute(c.verticalTouchEnd),b.ha(c.verticalTouchInit)||b.setAttribute(c.verticalTouchInit,JSON.stringify(d.getTouchPoints(a)))),d.setupSwipe(a,b,c),b.ha(c.tapIndicator)&&!b.ha(c.tapStart)&&b.setAttribute(c.tapStart,setTimeout(function(){clearTimeout(b.getAttribute(c.tapStart)),b.removeAttribute(c.doubleTapStart)},700)),d.doDoubleTap(a,b,c)},endTouchHandler:function(a,b,c){var d=this;c=this.settings,a.preventDefault(),b.ha(c.moveTouchInitial)&&b.setAttribute(c.moveTouchEnded,"true"),b.ha(c.horizontalIndicator)&&b.setAttribute(c.horizontalTouchEnd,"true"),b.ha(c.verticalIndicator)&&b.setAttribute(c.verticalTouchEnd,"true"),b.ha(c.swipeRight)&&(d.swipping=!1,b.setAttribute(c.swipeRightEnd,"true"),b.removeAttribute(c.swipeRightInit)),b.ha(c.swipeLeft)&&(d.swipping=!1,b.setAttribute(c.swipeLeftEnd,"true"),b.removeAttribute(c.swipeLeftInit)),b.ha(c.swipeUp)&&(d.swipping=!1,b.setAttribute(c.swipeUpEnd,"true"),b.removeAttribute(c.swipeUpInit)),b.ha(c.swipeDown)&&(d.swipping=!1,b.setAttribute(c.swipeDownEnd,"true"),b.removeAttribute(c.swipeDownInit)),b.ha(c.tapIndicator)&&b.ha(c.tapStart)&&(d.tapCallback(a),clearTimeout(b.getAttribute(c.tapStart)),b.removeAttribute(c.tapStart))},touchMoveHandler:function(a,b,c){var d=this;if(c=this.settings,a.preventDefault(),b.ha(c.moveIndicator)&&!b.ha(c.moveTouchEnded)&&b.ha(c.moveTouchInitial)&&(e=JSON.parse(b.getAttribute(c.moveTouchInitial)),f=d.getTouchPoints(a),g=d.calculateTranslation(e,f),b.style[d.support.transform]="translate3D("+g.translationX+"px, "+g.translationY+"px, 0)"),b.ha(c.horizontalIndicator)&&!b.ha(c.horizontalTouchEnd)&&b.ha(c.horizontalTouchInit)){console.log("should -horizontal move");var e=JSON.parse(b.getAttribute(c.horizontalTouchInit)),f=d.getTouchPoints(a),g=d.calculateTranslation(e,f);Math.abs(g.translationX)>d.settings.moveThreshold&&(b.style[d.support.transform]="translate3D("+g.translationX+"px, 0, 0)")}if(b.ha(c.verticalIndicator)&&!b.ha(c.verticalTouchEnd)&&b.ha(c.verticalTouchInit)){var e=JSON.parse(b.getAttribute(c.verticalTouchInit)),f=d.getTouchPoints(a),g=d.calculateTranslation(e,f);Math.abs(g.translationY)>d.settings.moveThreshold&&(b.style[d.support.transform]="translate3D(0, "+g.translationY+"px, 0)")}(b.ha(c.swipeRightInit)||b.ha(c.swipeLefttInit)||b.ha(c.swipeUpInit)||b.ha(c.swipeDownInit))&&(a.touches&&(a.clientX=a.touches[0].clientX,a.clientY=a.touches[0].clientY),d.processSwipe(b,a,c))},swipeRight:function(a,b){return this.setupIndicator(a,"swipeRightCallback",b,"swipeRightThreshold","swipeRight"),this},swipeLeft:function(a,b){return this.setupIndicator(a,"swipeLeftCallback",b,"swipeLeftThreshold","swipeLeft"),this},swipeUp:function(a,b){return this.setupIndicator(a,"swipeUpCallback",b,"swipeUpThreshold","swipeUp"),this},swipeDown:function(a,b){return this.setupIndicator(a,"swipeDownCallback",b,"swipeDownThreshold","swipeDown"),this},move:function(a){return this.setupIndicator(a,"moveCallback",0,"","moveIndicator"),this},horizontalMove:function(a){return this.setupIndicator(a,"moveHorizontalCallback",0,"","horizontalIndicator"),this},verticalMove:function(a){return this.setupIndicator(a,"moveVerticalCallback",0,"","verticalIndicator"),this},rotate:function(a){return this.setupIndicator(a,"rotateCallback",0,"","rotateIndicator"),this},scale:function(a){return this.setupIndicator(a,"scaleCallback",0,"","scaleIndicator"),this},tap:function(a){var c=this;return a||(a=b.noop),c.hasmsGesture?[].forEach.call(this.node,function(b){b.addEventListener("MSGestureTap",a,!1)}):this.setupIndicator(a,"tapCallback",0,"","tapIndicator"),this},dblTap:function(a){{var b=this.settings;d(".touch-log")}return a&&(b.doubleTapCallback=a),this.setupIndicator(a,"doubleTapCallback",0,"","doubleTapIndicator"),this},tapHold:function(a,b,c){var d=this;return a&&(d.tapHoldBeginCallback=a),this.hasmsGesture?(d.tapHoldBeginCallback=a,d.tapHoldEndCallback=b,d.tapHoldCancelCallback=c,[].forEach.call(this.node,function(a){d.preventTapHoldContext(a),a.addEventListener("MSGestureHold",function(a){d.tapHoldCallback.call(d,a)},!1)})):[].forEach.call(this.node,function(a){d.preventTapHoldContext(a),a.addEventListener(d.touchStart,function(b){d.setupTapHold(a,b)}),d.hasMouse&&a.addEventListener("mousedown",function(b){d.setupTapHold(a,b)})},!1),this},preventTapHoldContext:function(a){a.addEventListener("contextmenu",function(a){a.preventDefault()},!1)},setupTapHold:function(a,b){var c,d=this;c=setTimeout(function(){d.tapHoldBeginCallback.call(d,b),clearTimeout(c)},500),a.addEventListener(d.touchEnd,function(){clearTimeout(c)},!1),a.addEventListener(d.touchCancel,function(){clearTimeout(c)},!1)},tapHoldBeginCallback:b.noop,tapHoldEndCallback:b.noop,tapHoldCancelCallback:b.noop,tapHoldCallback:function(a){var b=this;a.preventDefault(),a.detail&a.MSGESTURE_FLAG_BEGIN&&b.tapHoldBeginCallback.call(b,a),a.detail&a.MSGESTURE_FLAG_END&&b.tapHoldEndCallback.call(b,a),a.detail&a.MSGESTURE_FLAG_CANCEL&&b.tapHoldCancelCallback.call(b,a)},settings:{allowPageScroll:!0,logging:!1,swipeRightThreshold:25,swipeLeftThreshold:-25,swipeUpThreshold:-25,swipeDownThreshold:25,moveThreshold:0,rotateThreshold:0,scaleThreshold:0,doubleTapThreshold:700,tapIndicator:"data-tap",tapStart:"data-tap-start",tapEnded:"data-tap-end",doubleTapIndicator:"data-dbltap",doubleTapStart:"data-dbltap-start",doubleTapEnded:"data-dbltap-end",rotateIndicator:"data-rotate",rotateEnded:"data-rotate-ended",rotateInitial:"data-rotate-initial",scaleIndicator:"data-scale",scaleEnded:"data-scale-ended",scaleInitial:"data-scale-initial",moveIndicator:"data-move",moveTouchEnded:"data-move-touch-ended",moveTouchInitial:"data-move-touch-initial",swipeRight:"data-swiperight",swipeRightInit:"data-swiperight-init",swipeRightEnd:"data-swiperight-end",swipeLeft:"data-swipeleft",swipeLeftInit:"data-swipeLeft-init",swipeLeftEnd:"data-swipeleft-end",swipeUp:"data-swipeup",swipeUpInit:"data-swipeup-init",swipeUpEnd:"data-swipeup-end",swipeDown:"data-swipedown",swipeDownInit:"data-swipedown-init",swipeDownEnd:"data-swipedown-end",horizontalIndicator:"data-move-horizontal",horizontalTouchInit:"data-horizontal-touch-initial",horizontalTouchEnd:"data-horizontal-touch-ended",verticalIndicator:"data-move-vertical",verticalTouchInit:"data-vertical-touch-initial",verticalTouchEnd:"data-vertical-touch-ended",autoMove:!0,autoRotate:!0,autoScale:!0,autoHorizontalMove:!0,autoVerticalMove:!0}},deeptissue.fn.init.prototype=deeptissue.fn,a.deeptissue=deeptissue}(window,$),function(a,b){"use strict";b.fn.move=function(a){return this.setupIndicator(a,"moveCallback",0,"","moveIndicator"),this},b.fn.horizontalMove=function(a){return this.setupIndicator(a,"moveHorizontalCallback",0,"","horizontalIndicator"),this},b.fn.verticalMove=function(a){return this.setupIndicator(a,"moveVerticalCallback",0,"","verticalIndicator"),this}}(window,deeptissue),function(a,b){"use strict";b.fn.tap=function(a){var b=this;return a||(a=function(){}),b.hasmsGesture?[].forEach.call(this.node,function(b){b.addEventListener("MSGestureTap",a,!1)}):this.setupIndicator(a,"tapCallback",0,"","tapIndicator"),this},b.fn.dblTap=function(a){{var b=this.settings;document.querySelector(".touch-log")}return a&&(b.doubleTapCallback=a),this.setupIndicator(a,"doubleTapCallback",0,"","doubleTapIndicator"),this},b.fn.tapHold=function(a){var b=this;return a&&(b.tapHoldBeginCallback=a),this.hasmsGesture?[].forEach.call(this.node,function(a){a.addEventListener("MSGestureHold",function(a){b.tapHoldCallback.call(b,a)},!1)}):[].forEach.call(this.node,function(a){a.addEventListener(b.touchStart,function(c){b.setupTapHold(a,c)}),b.hasMouse&&a.addEventListener("mousedown",function(c){b.setupTapHold(a,c)})},!1),this},b.fn.setupTapHold=function(a,b){var c,d=this;c=setTimeout(function(){d.tapHoldBeginCallback.call(d,b),clearTimeout(c)},500),a.addEventListener(d.touchEnd,function(){clearTimeout(c)},!1),a.addEventListener(d.touchCancel,function(){clearTimeout(c)},!1)},b.fn.tapHoldBeginCallback=function(){},b.fn.tapHoldEndCallback=function(){},b.fn.tapHoldCancelCallback=function(){},b.fn.tapHoldCallback=function(a){console.info("evt.detail - "+a.detail),a.detail&a.MSGESTURE_FLAG_BEGIN&&this.tapHoldBeginCallback.call(this,a),a.detail&a.MSGESTURE_FLAG_END&&this.tapHoldEndCallback.call(this,a),a.detail&a.MSGESTURE_FLAG_CANCEL&&this.tapHoldCancelCallback.call(this,a)}}(window,deeptissue),function(a,b){"use strict";b.fn.rotate=function(a){return this.setupIndicator(a,"rotateCallback",0,"","rotateIndicator"),this}}(window,deeptissue),function(a,b){"use strict";b.fn.scale=function(a){return this.setupIndicator(a,"scaleCallback",0,"","scaleIndicator"),this}}(window,deeptissue);
--------------------------------------------------------------------------------
/js/dev/deeptissue-swipetoselect.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/docluv/deeptissuejs/2455e8f32e198939fdb2266a2616606a2ac547f3/js/dev/deeptissue-swipetoselect.js
--------------------------------------------------------------------------------
/js/dev/deeptissue-twoswipe.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/docluv/deeptissuejs/2455e8f32e198939fdb2266a2616606a2ac547f3/js/dev/deeptissue-twoswipe.js
--------------------------------------------------------------------------------
/js/dev/deeptissue.move.js:
--------------------------------------------------------------------------------
1 | (function (window, deeptissue, undefined) {
2 |
3 | "use strict";
4 |
5 | //may add a threshold value, but for now just assume it should always fire.
6 | deeptissue.fn.move = function (callback) {
7 |
8 | this.setupIndicator(callback, "moveCallback", 0,
9 | "", "moveIndicator");
10 | return this;
11 |
12 | };
13 |
14 | deeptissue.fn.horizontalMove = function (callback) {
15 |
16 | this.setupIndicator(callback, "moveHorizontalCallback", 0,
17 | "", "horizontalIndicator");
18 | return this;
19 |
20 | };
21 |
22 | deeptissue.fn.verticalMove = function (callback) {
23 |
24 | this.setupIndicator(callback, "moveVerticalCallback", 0,
25 | "", "verticalIndicator");
26 | return this;
27 |
28 | };
29 |
30 | } (window, deeptissue));
31 |
32 |
--------------------------------------------------------------------------------
/js/dev/deeptissue.rotate.js:
--------------------------------------------------------------------------------
1 | (function (window, deeptissue, undefined) {
2 |
3 | "use strict";
4 |
5 | deeptissue.fn.rotate = function (callback) {
6 |
7 | this.setupIndicator(callback, "rotateCallback", 0,
8 | "", "rotateIndicator");
9 | return this;
10 |
11 | };
12 |
13 |
14 | } (window, deeptissue));
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/js/dev/deeptissue.scale.js:
--------------------------------------------------------------------------------
1 | (function (window, deeptissue, undefined) {
2 |
3 | "use strict";
4 |
5 | deeptissue.fn.scale = function (callback) {
6 |
7 | this.setupIndicator(callback, "scaleCallback", 0,
8 | "", "scaleIndicator");
9 | return this;
10 |
11 | };
12 |
13 |
14 | } (window, deeptissue));
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/js/dev/deeptissue.swipe.js:
--------------------------------------------------------------------------------
1 | (function (window, deeptissue, undefined) {
2 |
3 | "use strict";
4 |
5 | deeptissue.fn.swipeRight = function (callback, threshold) {
6 |
7 | this.setupIndicator(callback, "swipeRightCallback", threshold,
8 | "swipeRightThreshold", "swipeRight");
9 | return this;
10 | };
11 |
12 | deeptissue.fn.swipeLeft = function (callback, threshold) {
13 |
14 | this.setupIndicator(callback, "swipeLeftCallback", threshold, "swipeLeftThreshold", "swipeLeft");
15 | return this;
16 | };
17 |
18 | deeptissue.fn.swipeUp = function (callback, threshold) {
19 |
20 | this.setupIndicator(callback, "swipeUpCallback", threshold, "swipeUpThreshold", "swipeUp");
21 | return this;
22 | };
23 |
24 | deeptissue.fn.swipeDown = function (callback, threshold) {
25 |
26 | this.setupIndicator(callback, "swipeDownCallback", threshold, "swipeDownThreshold", "swipeDown");
27 | return this;
28 | };
29 |
30 | } (window, deeptissue));
31 |
32 |
--------------------------------------------------------------------------------
/js/dev/deeptissue.tap.js:
--------------------------------------------------------------------------------
1 | (function (window, deeptissue, undefined) {
2 |
3 | "use strict";
4 |
5 | //Tap
6 | deeptissue.fn.tap = function (callback) {
7 |
8 | var that = this;
9 |
10 | if (!callback) {
11 | callback = function () { };
12 | }
13 |
14 | if (that.hasmsGesture) {
15 |
16 | [ ].forEach.call(this.node, function (el) {
17 | el.addEventListener("MSGestureTap", callback, false);
18 | });
19 |
20 | } else {
21 |
22 | this.setupIndicator(callback, "tapCallback", 0,
23 | "", "tapIndicator");
24 |
25 | }
26 |
27 | return this;
28 |
29 | };
30 |
31 | //Double Tap Members
32 |
33 | deeptissue.fn.dblTap = function (callback) {
34 |
35 | var that = this,
36 | settings = this.settings,
37 | tl = document.querySelector(".touch-log");
38 |
39 | if (callback) {
40 | settings.doubleTapCallback = callback;
41 | }
42 |
43 | this.setupIndicator(callback, "doubleTapCallback", 0,
44 | "", "doubleTapIndicator");
45 |
46 | return this;
47 |
48 | };
49 |
50 | //Tap Hold Members
51 | deeptissue.fn.tapHold = function (callback, endcallback, cancelcallback) {
52 |
53 | var that = this;
54 |
55 | if (callback) {
56 | that.tapHoldBeginCallback = callback;
57 | }
58 |
59 | if (this.hasmsGesture) {
60 |
61 | [ ].forEach.call(this.node, function (el) {
62 | el.addEventListener("MSGestureHold", function (evt) {
63 | that.tapHoldCallback.call(that, evt);
64 | }, false);
65 | });
66 |
67 | } else {
68 |
69 | [ ].forEach.call(this.node, function (el) {
70 |
71 | el.addEventListener(that.touchStart, function (evt) {
72 | that.setupTapHold(el, evt);
73 | });
74 |
75 | if (that.hasMouse) {
76 | el.addEventListener("mousedown", function (evt) {
77 | that.setupTapHold(el, evt);
78 | });
79 | }
80 |
81 | }, false);
82 |
83 | }
84 |
85 | return this;
86 | };
87 |
88 | deeptissue.fn.setupTapHold = function (el, evt) {
89 |
90 | var that = this,
91 | tht;
92 |
93 | tht = setTimeout(function () {
94 | that.tapHoldBeginCallback.call(that, evt);
95 | clearTimeout(tht);
96 | }, 500);
97 |
98 | el.addEventListener(that.touchEnd, function (evt) {
99 | clearTimeout(tht);
100 | }, false);
101 |
102 | el.addEventListener(that.touchCancel, function (evt) {
103 | clearTimeout(tht);
104 | }, false);
105 |
106 | };
107 |
108 | deeptissue.fn.tapHoldBeginCallback = function () { };
109 | deeptissue.fn.tapHoldEndCallback = function () { };
110 | deeptissue.fn.tapHoldCancelCallback = function () { };
111 |
112 | deeptissue.fn.tapHoldCallback = function (evt) {
113 |
114 | console.info("evt.detail - " + evt.detail);
115 |
116 | if (evt.detail & evt.MSGESTURE_FLAG_BEGIN) {
117 |
118 | // Begin signals the start of a gesture. For the Hold gesture, this means the user has been holding long enough in place that the gesture will become a complete press & hold if the finger is lifted.
119 | this.tapHoldBeginCallback.call(this, evt);
120 | }
121 |
122 | if (evt.detail & evt.MSGESTURE_FLAG_END) {
123 |
124 | // End signals the end of the gesture.
125 | this.tapHoldEndCallback.call(this, evt);
126 | }
127 |
128 | if (evt.detail & evt.MSGESTURE_FLAG_CANCEL) {
129 |
130 | // Cancel signals the user started the gesture but cancelled it. For hold, this occurs when the user drags away before lifting. This flag is sent together with the End flag, signaling the gesture recognition is complete.
131 | this.tapHoldCancelCallback.call(this, evt);
132 | }
133 |
134 | };
135 |
136 |
137 | } (window, deeptissue));
138 |
139 |
140 |
--------------------------------------------------------------------------------
/js/dev/license.txt:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Chris Love
3 |
4 | http://deeptissuejs.com
5 | https://github.com/docluv/deeptissuejs
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | 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.
12 | */
13 |
14 |
--------------------------------------------------------------------------------
/js/dev/mbp.js:
--------------------------------------------------------------------------------
1 | /*
2 | Extending the functionality of the Mobile Boilerplate helper object.
3 | */
4 |
5 | var _gaq = _gaq || undefined,
6 | $ = $ || {};
7 |
8 | (function (document, $) {
9 |
10 | "use strict";
11 |
12 | window.$ = $ || {};
13 |
14 | // If we split this up into two functions we can reuse
15 | // this function if we aren't doing full page reloads.
16 |
17 | // If we cache this we don't need to re-calibrate everytime we call
18 | // the hide url bar
19 | $.BODY_SCROLL_TOP = false;
20 |
21 | // So we don't redefine this function everytime we
22 | // we call hideUrlBar
23 | $.getScrollTop = function () {
24 | var win = window;
25 | var doc = document;
26 |
27 | return win.pageYOffset || doc.compatMode === 'CSS1Compat' && doc.documentElement.scrollTop || doc.body.scrollTop || 0;
28 | };
29 |
30 | // It should be up to the mobile
31 | $.hideUrlBar = function () {
32 | var win = window;
33 |
34 | // if there is a hash, or $.BODY_SCROLL_TOP hasn't been set yet, wait till that happens
35 | if (!location.hash && $.BODY_SCROLL_TOP !== false) {
36 | win.scrollTo(0, $.BODY_SCROLL_TOP === 1 ? 0 : 1);
37 | }
38 | };
39 |
40 | $.hideUrlBarOnLoad = function () {
41 | var win = window;
42 | var doc = win.document;
43 | var bodycheck;
44 |
45 | // If there's a hash, or addEventListener is undefined, stop here
46 | if (!location.hash && win.addEventListener) {
47 |
48 | // scroll to 1
49 | window.scrollTo(0, 1);
50 | $.BODY_SCROLL_TOP = 1;
51 |
52 | // reset to 0 on bodyready, if needed
53 | bodycheck = setInterval(function () {
54 | if (doc.body) {
55 | clearInterval(bodycheck);
56 | $.BODY_SCROLL_TOP = $.getScrollTop();
57 | $.hideUrlBar();
58 | }
59 | }, 15);
60 |
61 | win.addEventListener('load', function () {
62 | setTimeout(function () {
63 | // at load, if user hasn't scrolled more than 20 or so...
64 | if ($.getScrollTop() < 20) {
65 | // reset to hide addr bar at onload
66 | $.hideUrlBar();
67 | }
68 | }, 0);
69 | });
70 | }
71 | };
72 |
73 |
74 | //simple version of the jQuery function
75 | $.extend = function () {
76 |
77 | var target = arguments[0] || {},
78 | i = 1,
79 | src,
80 | name,
81 | copy,
82 | options,
83 | length = arguments.length;
84 |
85 | for (i = 1; i < length; i++) {
86 | // Only deal with non-null/undefined values
87 | if ((options = arguments[i]) !== null) {
88 | // Extend the base object
89 | for (name in options) {
90 | src = target[name];
91 | copy = options[name];
92 |
93 | // Prevent never-ending loop
94 | if (target === copy) {
95 | continue;
96 | }
97 |
98 | if (copy !== undefined) {
99 | target[name] = copy;
100 | }
101 | }
102 | }
103 | }
104 |
105 | return target;
106 |
107 | };
108 |
109 | $.loadScript = function (id, url, callback) {
110 |
111 | if (!document.getElementById(id)) {
112 |
113 | var script = document.createElement("script");
114 |
115 | script.type = "text/javascript";
116 | script.id = id;
117 |
118 | if (script.readyState) { //IE
119 |
120 | script.onreadystatechange = function () {
121 |
122 | if (script.readyState === "loaded" ||
123 |
124 | script.readyState === "complete") {
125 | script.onreadystatechange = null;
126 | callback();
127 |
128 | }
129 |
130 | };
131 |
132 | } else { //Others
133 | script.onload = function () {
134 | callback();
135 | };
136 | }
137 |
138 | script.src = url;
139 | document.body.appendChild(script);
140 |
141 | } else {
142 | callback();
143 | }
144 | };
145 |
146 | $.getVendorPropertyName = function (prop) {
147 |
148 | var prefixes = ['Moz', 'Webkit', 'O', 'ms'],
149 | vendorProp, i,
150 | div = document.createElement('div'),
151 | prop_ = prop.charAt(0).toUpperCase() + prop.substr(1);
152 |
153 | if (prop in div.style) {
154 | return prop;
155 | }
156 |
157 | for (i = 0; i < prefixes.length; ++i) {
158 |
159 | vendorProp = prefixes[i] + prop_;
160 |
161 | if (vendorProp in div.style) {
162 | return vendorProp;
163 | }
164 |
165 | }
166 |
167 | // Avoid memory leak in IE.
168 | this.div = null;
169 | };
170 |
171 | $.checkTransform3dSupport = function () {
172 |
173 | var div = document.createElement('div'),
174 | transform = $.getVendorPropertyName('transform');
175 |
176 | div.style[transform] = '';
177 | div.style[transform] = 'rotateY(90deg)';
178 | return div.style[transform] !== '';
179 |
180 | };
181 |
182 | $.buildVendorNames = function () {
183 |
184 | return {
185 | // Check for the browser's transitions support.
186 | transition: $.getVendorPropertyName('transition'),
187 | transitionDelay: $.getVendorPropertyName('transitionDelay'),
188 | transform: $.getVendorPropertyName('transform'),
189 | transformOrigin: $.getVendorPropertyName('transformOrigin'),
190 | transform3d: $.checkTransform3dSupport()
191 |
192 | };
193 |
194 | };
195 |
196 | window.AddEvent = function (ele, evt, callback, useCapture) {
197 |
198 | useCapture = useCapture || false;
199 |
200 | if (!callback || !evt || !ele) {
201 | return; //nothing to do here
202 | }
203 |
204 | if (ele.addEventListener) {
205 | ele.addEventListener(evt, callback, useCapture);
206 | } else if (ele.attachEvent) {
207 | ele.attachEvent(evt, callback);
208 | }
209 |
210 | };
211 |
212 | //helps with old Android and iOS web apps
213 | $.parseLocalStorage = function (key) {
214 |
215 | var value = localStorage.getItem(key);
216 |
217 | if (!value) {
218 | return {};
219 | }
220 |
221 | return JSON.parse(value) || {};
222 |
223 | };
224 |
225 | $.s4 = function () {
226 | return Math.floor((1 + Math.random()) * 0x10000)
227 | .toString(16)
228 | .substring(1);
229 | };
230 |
231 | $.guid = function () {
232 | return $.s4() + $.s4() + '-' + $.s4() + '-' + $.s4() + '-' +
233 | $.s4() + '-' + $.s4() + $.s4() + $.s4();
234 | };
235 |
236 | $.data = function (view, name, val) {
237 |
238 | val = val || "";
239 |
240 | return (view.hasAttribute("data-" + name) ? view.getAttribute("data-" + name) : val);
241 |
242 | };
243 |
244 | $.removeClass = function(view, cssClass){
245 |
246 | view.className = view.className
247 | .replace(" " + cssClass + " ", " ")
248 | .replace(" " + cssClass, "")
249 | .replace(cssClass + " ", "");
250 |
251 | };
252 |
253 | $.addClass = function (view, cssClass) {
254 |
255 | if (!view || !cssClass) {
256 | return;
257 | }
258 |
259 | if (view.classList) {
260 |
261 | view.classList.add(cssClass);
262 |
263 | } else {
264 |
265 | view.className += " " + cssClass;
266 |
267 | }
268 |
269 | };
270 |
271 | $.attr = function (view, attr, value) {
272 |
273 | if (!view) {
274 | return;
275 | }
276 |
277 | if (value === undefined) {
278 |
279 | return (view.hasAttribute(attr) ? view.getAttribute(attr) : null);
280 |
281 | } else {
282 |
283 | view.setAttribute(attr, value);
284 | return this; //chain it why not?
285 |
286 | }
287 |
288 | };
289 |
290 | $.noop = function () { };
291 |
292 | })(document, $);
--------------------------------------------------------------------------------
/js/specs/Util.Tests.js:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | assertContains = function (array, fun, message) {
5 | var arrayToTest = array.subscribe === undefined ? array : array();
6 | var hasAny = $.grep(arrayToTest, fun).length > 0;
7 | ok(hasAny, message + "\n fun: " + fun);
8 | };
9 |
10 | assertNotContains = function (array, fun, message) {
11 | var arrayToTest = array.subscribe === undefined ? array : array();
12 | var hasAny = $.grep(arrayToTest, fun).length > 0;
13 | ok(!hasAny, message + "\n fun: " + fun);
14 | };
15 |
16 | atLeast = function(actual, value, message) {
17 |
18 | if(!actual){
19 | QUnit.push(false, actual, message);
20 | return;
21 | }
22 |
23 | QUnit.push(actual >= value, actual, message);
24 | };
25 |
26 | noMoreThan = function(actual, value, message) {
27 | QUnit.push(actual <= value, actual, message);
28 | };
29 |
30 | greaterThan = function(actual, value, message) {
31 | QUnit.push(actual > value, actual, message);
32 | };
33 |
34 | lessThan = function(actual, value, message) {
35 | QUnit.push(actual < value, actual, message);
36 | };
37 |
38 | eitherOr = function(actual, value1, value2, message) {
39 | QUnit.push((actual === value1 || actual === value2), actual, message);
40 | };
41 |
42 | anyOf = function(actual, values, message) {
43 |
44 | var hasValue = false,
45 | i = 0;
46 |
47 | for(i = values.length - 1; i >= 0; i--){
48 | if(actual === values[i]){
49 | hasValue = true;
50 | i = -1;
51 | }
52 | }
53 |
54 | QUnit.push(hasValue, actual, message);
55 | };
56 |
57 |
58 | arrayContains = function(actual, value, message) {
59 |
60 | if(!actual){
61 | QUnit.push(false, actual, message);
62 | return;
63 | }
64 |
65 | var hasValue = false,
66 | i = 0;
67 |
68 | for(i = actual.length - 1; i >= 0; i--){
69 |
70 | if(value === actual[i]){
71 | hasValue = true;
72 | }
73 |
74 | };
75 |
76 | QUnit.push(hasValue, actual, message);
77 | };
78 |
79 | arrayDoesContain = function(actual, value, message) {
80 |
81 | var hasValue = true,
82 | i = 0;
83 |
84 | for(i = actual.length - 1; i >= 0; i--){
85 |
86 | if(value === actual[i]){
87 | hasValue = false;
88 | }
89 |
90 | };
91 |
92 | QUnit.push(hasValue, actual, message);
93 | };
94 |
95 |
96 | (function( $ ){
97 |
98 | function escapeHtml(s) {
99 | if (!s) {
100 | return "";
101 | }
102 | s = s + "";
103 | return s.replace(/[\&"<>\\]/g, function(s) {
104 | switch(s) {
105 | case "&": return "&";
106 | case "\\": return "\\\\";
107 | case '"': return '\"';
108 | case "<": return "<";
109 | case ">": return ">";
110 | default: return s;
111 | }
112 | }).replace(/(\r\n|\n|\r)/gm, " ");
113 | }
114 |
115 | function pushSelectorAssertToQunit(result, message, content, expectedMessage, expectedValue){
116 | QUnit.log({
117 | result: result,
118 | message: message,
119 | actual: content,
120 | expected: expectedMessage + " " + expectedValue
121 | });
122 |
123 | QUnit.config.current.assertions.push({
124 | result: !!result,
125 | message: message || ("
" + escapeHtml(style_html(content)) + "
" + expectedMessage + " " + expectedValue + "
")
126 | });
127 | }
128 |
129 | $.fn.assertContains = function(selector, message) {
130 | pushSelectorAssertToQunit($(selector, this).length > 0, message, this.html(), "should contains", selector);
131 | return this;
132 | };
133 |
134 | $.fn.assertNotContains = function(selector, message) {
135 | pushSelectorAssertToQunit($(selector, this).length === 0, message, this.html(), "should not contains", selector);
136 | return this;
137 | };
138 |
139 | $.fn.assertContainsText = function(text, message) {
140 | pushSelectorAssertToQunit(this.is(":contains('" + text + "')"), message, this.html(), "should contains text", text);
141 | return this;
142 | };
143 |
144 | $.fn.assertNotContainsText = function(text, message) {
145 | pushSelectorAssertToQunit(!this.is(":contains('" + text + "')"), message, this.html(), "should not contains text", text);
146 | return this;
147 | };
148 |
149 | $.fn.assertIsVisible = function (message){
150 | QUnit.push(this.is(":visible"), this.is(":visible") ? "visible" : "hidden", "visible", message);
151 | return this;
152 | };
153 |
154 | $.fn.assertIsHidden = function (message){
155 | QUnit.push(this.is(":hidden"), this.is(":hidden") ? "hidden" : "visible", "hidden", message);
156 | return this;
157 | };
158 |
159 | $.fn.assertEventBound = function(eventName, message) {
160 |
161 | $.each(this, function(i, e){
162 | //looping through because a selector might have multiple elements
163 | var hasEvent = false;
164 |
165 | $.each($(e).data('events'), function(j, evt){
166 |
167 | //looping through because an element could contain multiple bindings.
168 | if(eventName === j.toString()){
169 | hasEvent = true;
170 | }
171 |
172 | });
173 |
174 | QUnit.push(hasEvent, "event " + eventName + " bound", message);
175 |
176 | });
177 |
178 | return this;
179 | };
180 |
181 |
182 | })( jQuery );
183 |
184 |
--------------------------------------------------------------------------------
/js/specs/beautify-html.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Style HTML
4 | ---------------
5 |
6 | Written by Nochum Sossonko, (nsossonko@hotmail.com)
7 |
8 | Based on code initially developed by: Einar Lielmanis,
9 | http://jsbeautifier.org/
10 |
11 |
12 | You are free to use this in any way you want, in case you find this useful or working for you.
13 |
14 | Usage:
15 | style_html(html_source);
16 |
17 | style_html(html_source, options);
18 |
19 | The options are:
20 | indent_size (default 4) — indentation size,
21 | indent_char (default space) — character to indent with,
22 | max_char (default 70) - maximum amount of characters per line,
23 | brace_style (default "collapse") - "collapse" | "expand" | "end-expand"
24 | put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.
25 | unformatted (default ['a']) - list of tags, that shouldn't be reformatted
26 | indent_scripts (default normal) - "keep"|"separate"|"normal"
27 |
28 | e.g.
29 |
30 | style_html(html_source, {
31 | 'indent_size': 2,
32 | 'indent_char': ' ',
33 | 'max_char': 78,
34 | 'brace_style': 'expand',
35 | 'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u']
36 | });
37 | */
38 |
39 | function style_html(html_source, options) {
40 | //Wrapper function to invoke all the necessary constructors and deal with the output.
41 |
42 | var multi_parser,
43 | indent_size,
44 | indent_character,
45 | max_char,
46 | brace_style;
47 |
48 | options = options || {};
49 | indent_size = options.indent_size || 4;
50 | indent_character = options.indent_char || ' ';
51 | brace_style = options.brace_style || 'collapse';
52 | max_char = options.max_char || '70';
53 | unformatted = options.unformatted || ['a'];
54 |
55 | function Parser() {
56 |
57 | this.pos = 0; //Parser position
58 | this.token = '';
59 | this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
60 | this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
61 | parent: 'parent1',
62 | parentcount: 1,
63 | parent1: ''
64 | };
65 | this.tag_type = '';
66 | this.token_text = this.last_token = this.last_text = this.token_type = '';
67 |
68 | this.Utils = { //Uilities made available to the various functions
69 | whitespace: "\n\r\t ".split(''),
70 | single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed'.split(','), //all the single tags for HTML
71 | extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them
72 | in_array: function (what, arr) {
73 | for (var i=0; i= this.input.length) {
89 | return content.length?content.join(''):['', 'TK_EOF'];
90 | }
91 |
92 | input_char = this.input.charAt(this.pos);
93 | this.pos++;
94 | this.line_char_count++;
95 |
96 | if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
97 | if (content.length) {
98 | space = true;
99 | }
100 | this.line_char_count--;
101 | continue; //don't want to insert unnecessary space
102 | }
103 | else if (space) {
104 | if (this.line_char_count >= this.max_char) { //insert a line when the max_char is reached
105 | content.push('\n');
106 | for (var i=0; i', 'igm');
129 | reg_match.lastIndex = this.pos;
130 | var reg_array = reg_match.exec(this.input);
131 | var end_script = reg_array?reg_array.index:this.input.length; //absolute end of script
132 | if(this.pos < end_script) { //get everything in between the script tags
133 | content = this.input.substring(this.pos, end_script);
134 | this.pos = end_script;
135 | }
136 | return content;
137 | }
138 |
139 | this.record_tag = function (tag){ //function to record a tag and its parent in this.tags Object
140 | if (this.tags[tag + 'count']) { //check for the existence of this tag type
141 | this.tags[tag + 'count']++;
142 | this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
143 | }
144 | else { //otherwise initialize this tag type
145 | this.tags[tag + 'count'] = 1;
146 | this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
147 | }
148 | this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
149 | this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
150 | }
151 |
152 | this.retrieve_tag = function (tag) { //function to retrieve the opening tag to the corresponding closer
153 | if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
154 | var temp_parent = this.tags.parent; //check to see if it's a closable tag.
155 | while (temp_parent) { //till we reach '' (the initial value);
156 | if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
157 | break;
158 | }
159 | temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
160 | }
161 | if (temp_parent) { //if we caught something
162 | this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
163 | this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
164 | }
165 | delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
166 | delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
167 | if (this.tags[tag + 'count'] == 1) {
168 | delete this.tags[tag + 'count'];
169 | }
170 | else {
171 | this.tags[tag + 'count']--;
172 | }
173 | }
174 | }
175 |
176 | this.get_tag = function () { //function to get a full tag and parse its type
177 | var input_char = '';
178 | var content = [];
179 | var space = false;
180 |
181 | do {
182 | if (this.pos >= this.input.length) {
183 | return content.length?content.join(''):['', 'TK_EOF'];
184 | }
185 |
186 | input_char = this.input.charAt(this.pos);
187 | this.pos++;
188 | this.line_char_count++;
189 |
190 | if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
191 | space = true;
192 | this.line_char_count--;
193 | continue;
194 | }
195 |
196 | if (input_char === "'" || input_char === '"') {
197 | if (!content[1] || content[1] !== '!') { //if we're in a comment strings don't get treated specially
198 | input_char += this.get_unformatted(input_char);
199 | space = true;
200 | }
201 | }
202 |
203 | if (input_char === '=') { //no space before =
204 | space = false;
205 | }
206 |
207 | if (content.length && content[content.length-1] !== '=' && input_char !== '>'
208 | && space) { //no space after = or before >
209 | if (this.line_char_count >= this.max_char) {
210 | this.print_newline(false, content);
211 | this.line_char_count = 0;
212 | }
213 | else {
214 | content.push(' ');
215 | this.line_char_count++;
216 | }
217 | space = false;
218 | }
219 | content.push(input_char); //inserts character at-a-time (or string)
220 | } while (input_char !== '>');
221 |
222 | var tag_complete = content.join('');
223 | var tag_index;
224 | if (tag_complete.indexOf(' ') != -1) { //if there's whitespace, thats where the tag name ends
225 | tag_index = tag_complete.indexOf(' ');
226 | }
227 | else { //otherwise go with the tag ending
228 | tag_index = tag_complete.indexOf('>');
229 | }
230 | var tag_check = tag_complete.substring(1, tag_index).toLowerCase();
231 | if (tag_complete.charAt(tag_complete.length-2) === '/' ||
232 | this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
233 | this.tag_type = 'SINGLE';
234 | }
235 | else if (tag_check === 'script') { //for later script handling
236 | this.record_tag(tag_check);
237 | this.tag_type = 'SCRIPT';
238 | }
239 | else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)
240 | this.record_tag(tag_check);
241 | this.tag_type = 'STYLE';
242 | }
243 | else if (this.Utils.in_array(tag_check, unformatted)) { // do not reformat the "unformatted" tags
244 | var comment = this.get_unformatted(''+tag_check+'>', tag_complete); //...delegate to get_unformatted function
245 | content.push(comment);
246 | this.tag_type = 'SINGLE';
247 | }
248 | else if (tag_check.charAt(0) === '!') { //peek for so...
251 | var comment = this.get_unformatted('-->', tag_complete); //...delegate to get_unformatted
252 | content.push(comment);
253 | }
254 | this.tag_type = 'START';
255 | }
256 | else if (tag_check.indexOf('[endif') != -1) {//peek for ', tag_complete);
267 | content.push(comment);
268 | this.tag_type = 'SINGLE';
269 | }
270 | }
271 | else {
272 | if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
273 | this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
274 | this.tag_type = 'END';
275 | }
276 | else { //otherwise it's a start-tag
277 | this.record_tag(tag_check); //push it on the tag stack
278 | this.tag_type = 'START';
279 | }
280 | if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
281 | this.print_newline(true, this.output);
282 | }
283 | }
284 | return content.join(''); //returns fully formatted tag
285 | }
286 |
287 | this.get_unformatted = function (delimiter, orig_tag) { //function to return unformatted content in its entirety
288 |
289 | if (orig_tag && orig_tag.indexOf(delimiter) != -1) {
290 | return '';
291 | }
292 | var input_char = '';
293 | var content = '';
294 | var space = true;
295 | do {
296 |
297 | if (this.pos >= this.input.length) {
298 | return content;
299 | }
300 |
301 | input_char = this.input.charAt(this.pos);
302 | this.pos++
303 |
304 | if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
305 | if (!space) {
306 | this.line_char_count--;
307 | continue;
308 | }
309 | if (input_char === '\n' || input_char === '\r') {
310 | content += '\n';
311 | /* Don't change tab indention for unformatted blocks. If using code for html editing, this will greatly affect
tags if they are specified in the 'unformatted array'
312 | for (var i=0; i 0) {
414 | this.indent_level--;
415 | }
416 | }
417 | }
418 | return this;
419 | }
420 |
421 | /*_____________________--------------------_____________________*/
422 |
423 | multi_parser = new Parser(); //wrapping functions Parser
424 | multi_parser.printer(html_source, indent_character, indent_size, max_char, brace_style); //initialize starting values
425 |
426 | while (true) {
427 | var t = multi_parser.get_token();
428 | multi_parser.token_text = t[0];
429 | multi_parser.token_type = t[1];
430 |
431 | if (multi_parser.token_type === 'TK_EOF') {
432 | break;
433 | }
434 |
435 | switch (multi_parser.token_type) {
436 | case 'TK_TAG_START':
437 | multi_parser.print_newline(false, multi_parser.output);
438 | multi_parser.print_token(multi_parser.token_text);
439 | multi_parser.indent();
440 | multi_parser.current_mode = 'CONTENT';
441 | break;
442 | case 'TK_TAG_STYLE':
443 | case 'TK_TAG_SCRIPT':
444 | multi_parser.print_newline(false, multi_parser.output);
445 | multi_parser.print_token(multi_parser.token_text);
446 | multi_parser.current_mode = 'CONTENT';
447 | break;
448 | case 'TK_TAG_END':
449 | //Print new line only if the tag has no content and has child
450 | if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
451 | var tag_name = multi_parser.token_text.match(/\w+/)[0];
452 | var tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length -1].match(/<\s*(\w+)/);
453 | if (tag_extracted_from_last_output === null || tag_extracted_from_last_output[1] !== tag_name)
454 | multi_parser.print_newline(true, multi_parser.output);
455 | }
456 | multi_parser.print_token(multi_parser.token_text);
457 | multi_parser.current_mode = 'CONTENT';
458 | break;
459 | case 'TK_TAG_SINGLE':
460 | multi_parser.print_newline(false, multi_parser.output);
461 | multi_parser.print_token(multi_parser.token_text);
462 | multi_parser.current_mode = 'CONTENT';
463 | break;
464 | case 'TK_CONTENT':
465 | if (multi_parser.token_text !== '') {
466 | multi_parser.print_token(multi_parser.token_text);
467 | }
468 | multi_parser.current_mode = 'TAG';
469 | break;
470 | case 'TK_STYLE':
471 | case 'TK_SCRIPT':
472 | if (multi_parser.token_text !== '') {
473 | multi_parser.output.push('\n');
474 | var text = multi_parser.token_text;
475 | if (multi_parser.token_type == 'TK_SCRIPT') {
476 | var _beautifier = typeof js_beautify == 'function' && js_beautify;
477 | } else if (multi_parser.token_type == 'TK_STYLE') {
478 | var _beautifier = typeof css_beautify == 'function' && css_beautify;
479 | }
480 |
481 | if (options.indent_scripts == "keep") {
482 | var script_indent_level = 0;
483 | } else if (options.indent_scripts == "separate") {
484 | var script_indent_level = -multi_parser.indent_level;
485 | } else {
486 | var script_indent_level = 1;
487 | }
488 |
489 | var indentation = multi_parser.get_full_indent(script_indent_level);
490 | if (_beautifier) {
491 | // call the Beautifier if avaliable
492 | text = _beautifier(text.replace(/^\s*/, indentation), options);
493 | } else {
494 | // simply indent the string otherwise
495 | var white = text.match(/^\s*/)[0];
496 | var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
497 | var reindent = multi_parser.get_full_indent(script_indent_level -_level);
498 | text = text.replace(/^\s*/, indentation)
499 | .replace(/\r\n|\r|\n/g, '\n' + reindent)
500 | .replace(/\s*$/, '');
501 | }
502 | if (text) {
503 | multi_parser.print_token(text);
504 | multi_parser.print_newline(true, multi_parser.output);
505 | }
506 | }
507 | multi_parser.current_mode = 'TAG';
508 | break;
509 | }
510 | multi_parser.last_token = multi_parser.token_type;
511 | multi_parser.last_text = multi_parser.token_text;
512 | }
513 | return multi_parser.output.join('');
514 | }
515 |
--------------------------------------------------------------------------------
/js/specs/deeptissue.tests.js:
--------------------------------------------------------------------------------
1 | localStorage.clear();
2 |
3 | var target,
4 | foo = function(){};
5 |
6 | module("DeepTissue Unit Tests", {
7 | setup: function () {
8 |
9 | target = document.querySelectorAll("#testtarget");
10 |
11 | },
12 | teardown: function () {
13 |
14 | }
15 | });
16 |
17 |
18 | test("Verify We Have deep tissue with expected members", function () {
19 |
20 | //basic sainty assertions to know members are present
21 | ok(deeptissue, "movie object should exist");
22 | ok(deeptissue.fn.move, "move function should exist");
23 | ok(deeptissue.fn.horizontalMove, "horizontalMove function should exist");
24 | ok(deeptissue.fn.verticalMove, "verticalMove function should exist");
25 | ok(deeptissue.fn.rotate, "rotate function should exist");
26 | ok(deeptissue.fn.scale, "scale function should exist");
27 | ok(deeptissue.fn.swipeRight, "swipeRight function should exist");
28 | ok(deeptissue.fn.swipeLeft, "swipeLeft function should exist");
29 | ok(deeptissue.fn.swipeUp, "swipeUp function should exist");
30 | ok(deeptissue.fn.swipeDown, "swipeDown function should exist");
31 | ok(deeptissue.fn.tap, "tap function should exist");
32 | ok(deeptissue.fn.dblTap, "dblTap function should exist");
33 | ok(deeptissue.fn.tapHold, "tapHold function should exist");
34 |
35 | });
36 |
37 | test("Verify can a new deeptissue instance and the node member is the target element", function () {
38 |
39 | var dt = deeptissue(target);
40 |
41 | equal(typeof dt, "object", "deeptissue object should exist");
42 | equal(dt.node, target, "should be the target node");
43 |
44 | });
45 |
46 | test("Verify move method applies desired data- attributes and callback setup", function () {
47 |
48 | var dt = deeptissue(target).move(foo);
49 |
50 | equal(dt.moveCallback, foo, "moveCallback should be foo");
51 | ok(target[0].hasAttribute(dt.settings.moveIndicator), "should have moveIndicator");
52 | //ok(dt.hasAttribute(dt.settings.moveIndicator), "should have moveIndicator");
53 | //ok(dt.hasAttribute(dt.settings.moveIndicator), "should have moveIndicator");
54 | //ok(dt.hasAttribute(dt.settings.moveIndicator), "should have moveIndicator");
55 |
56 | });
57 |
58 |
--------------------------------------------------------------------------------
/js/specs/jquery.mockjax.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MockJax - jQuery Plugin to Mock Ajax requests
3 | *
4 | * Version: 1.5.1
5 | * Released:
6 | * Home: http://github.com/appendto/jquery-mockjax
7 | * Author: Jonathan Sharp (http://jdsharp.com)
8 | * License: MIT,GPL
9 | *
10 | * Copyright (c) 2011 appendTo LLC.
11 | * Dual licensed under the MIT or GPL licenses.
12 | * http://appendto.com/open-source-licenses
13 | */
14 | (function($) {
15 | var _ajax = $.ajax,
16 | mockHandlers = [],
17 | CALLBACK_REGEX = /=\?(&|$)/,
18 | jsc = (new Date()).getTime();
19 |
20 |
21 | // Parse the given XML string.
22 | function parseXML(xml) {
23 | if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
24 | DOMParser = function() { };
25 | DOMParser.prototype.parseFromString = function( xmlString ) {
26 | var doc = new ActiveXObject('Microsoft.XMLDOM');
27 | doc.async = 'false';
28 | doc.loadXML( xmlString );
29 | return doc;
30 | };
31 | }
32 |
33 | try {
34 | var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
35 | if ( $.isXMLDoc( xmlDoc ) ) {
36 | var err = $('parsererror', xmlDoc);
37 | if ( err.length == 1 ) {
38 | throw('Error: ' + $(xmlDoc).text() );
39 | }
40 | } else {
41 | throw('Unable to parse XML');
42 | }
43 | } catch( e ) {
44 | var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
45 | $(document).trigger('xmlParseError', [ msg ]);
46 | return undefined;
47 | }
48 | return xmlDoc;
49 | }
50 |
51 | // Trigger a jQuery event
52 | function trigger(s, type, args) {
53 | (s.context ? $(s.context) : $.event).trigger(type, args);
54 | }
55 |
56 | // Check if the data field on the mock handler and the request match. This
57 | // can be used to restrict a mock handler to being used only when a certain
58 | // set of data is passed to it.
59 | function isMockDataEqual( mock, live ) {
60 | var identical = false;
61 | // Test for situations where the data is a querystring (not an object)
62 | if (typeof live === 'string') {
63 | // Querystring may be a regex
64 | return $.isFunction( mock.test ) ? mock.test(live) : mock == live;
65 | }
66 | $.each(mock, function(k, v) {
67 | if ( live[k] === undefined ) {
68 | identical = false;
69 | return identical;
70 | } else {
71 | identical = true;
72 | if ( typeof live[k] == 'object' ) {
73 | return isMockDataEqual(mock[k], live[k]);
74 | } else {
75 | if ( $.isFunction( mock[k].test ) ) {
76 | identical = mock[k].test(live[k]);
77 | } else {
78 | identical = ( mock[k] == live[k] );
79 | }
80 | return identical;
81 | }
82 | }
83 | });
84 |
85 | return identical;
86 | }
87 |
88 | // Check the given handler should mock the given request
89 | function getMockForRequest( handler, requestSettings ) {
90 | // If the mock was registered with a function, let the function decide if we
91 | // want to mock this request
92 | if ( $.isFunction(handler) ) {
93 | return handler( requestSettings );
94 | }
95 |
96 | // Inspect the URL of the request and check if the mock handler's url
97 | // matches the url for this ajax request
98 | if ( $.isFunction(handler.url.test) ) {
99 | // The user provided a regex for the url, test it
100 | if ( !handler.url.test( requestSettings.url ) ) {
101 | return null;
102 | }
103 | } else {
104 | // Look for a simple wildcard '*' or a direct URL match
105 | var star = handler.url.indexOf('*');
106 | if (handler.url !== requestSettings.url && star === -1 ||
107 | !new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\\$&").replace('*', '.+')).test(requestSettings.url)) {
108 | return null;
109 | }
110 | }
111 |
112 | // Inspect the data submitted in the request (either POST body or GET query string)
113 | if ( handler.data && requestSettings.data ) {
114 | if ( !isMockDataEqual(handler.data, requestSettings.data) ) {
115 | // They're not identical, do not mock this request
116 | return null;
117 | }
118 | }
119 | // Inspect the request type
120 | if ( handler && handler.type &&
121 | handler.type.toLowerCase() != requestSettings.type.toLowerCase() ) {
122 | // The request type doesn't match (GET vs. POST)
123 | return null;
124 | }
125 |
126 | return handler;
127 | }
128 |
129 | // If logging is enabled, log the mock to the console
130 | function logMock( mockHandler, requestSettings ) {
131 | if ( window.console && console.log ) {
132 | var message = 'MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url;
133 | var request = $.extend({}, requestSettings);
134 |
135 | if (typeof console.log === 'function') {
136 | console.log(message, request);
137 | } else {
138 | try {
139 | console.log( message + ' ' + JSON.stringify(request) );
140 | } catch (e) {
141 | console.log(message);
142 | }
143 | }
144 | }
145 | }
146 |
147 | // Process the xhr objects send operation
148 | function _xhrSend(mockHandler, requestSettings, origSettings) {
149 |
150 | // This is a substitute for < 1.4 which lacks $.proxy
151 | var process = (function(that) {
152 | return function() {
153 | return (function() {
154 | // The request has returned
155 | this.status = mockHandler.status;
156 | this.statusText = mockHandler.statusText;
157 | this.readyState = 4;
158 |
159 | // We have an executable function, call it to give
160 | // the mock handler a chance to update it's data
161 | if ( $.isFunction(mockHandler.response) ) {
162 | mockHandler.response(origSettings);
163 | }
164 | // Copy over our mock to our xhr object before passing control back to
165 | // jQuery's onreadystatechange callback
166 | if ( requestSettings.dataType == 'json' && ( typeof mockHandler.responseText == 'object' ) ) {
167 | this.responseText = JSON.stringify(mockHandler.responseText);
168 | } else if ( requestSettings.dataType == 'xml' ) {
169 | if ( typeof mockHandler.responseXML == 'string' ) {
170 | this.responseXML = parseXML(mockHandler.responseXML);
171 | } else {
172 | this.responseXML = mockHandler.responseXML;
173 | }
174 | } else {
175 | this.responseText = mockHandler.responseText;
176 | }
177 | if( typeof mockHandler.status == 'number' || typeof mockHandler.status == 'string' ) {
178 | this.status = mockHandler.status;
179 | }
180 | if( typeof mockHandler.statusText === "string") {
181 | this.statusText = mockHandler.statusText;
182 | }
183 | // jQuery < 1.4 doesn't have onreadystate change for xhr
184 | if ( $.isFunction(this.onreadystatechange) ) {
185 | if( mockHandler.isTimeout) {
186 | this.status = -1;
187 | }
188 | this.onreadystatechange( mockHandler.isTimeout ? 'timeout' : undefined );
189 | } else if ( mockHandler.isTimeout ) {
190 | // Fix for 1.3.2 timeout to keep success from firing.
191 | this.status = -1;
192 | }
193 | }).apply(that);
194 | };
195 | })(this);
196 |
197 | if ( mockHandler.proxy ) {
198 | // We're proxying this request and loading in an external file instead
199 | _ajax({
200 | global: false,
201 | url: mockHandler.proxy,
202 | type: mockHandler.proxyType,
203 | data: mockHandler.data,
204 | dataType: requestSettings.dataType === "script" ? "text/plain" : requestSettings.dataType,
205 | complete: function(xhr, txt) {
206 | mockHandler.responseXML = xhr.responseXML;
207 | mockHandler.responseText = xhr.responseText;
208 | mockHandler.status = xhr.status;
209 | mockHandler.statusText = xhr.statusText;
210 | this.responseTimer = setTimeout(process, mockHandler.responseTime || 0);
211 | }
212 | });
213 | } else {
214 | // type == 'POST' || 'GET' || 'DELETE'
215 | if ( requestSettings.async === false ) {
216 | // TODO: Blocking delay
217 | process();
218 | } else {
219 | this.responseTimer = setTimeout(process, mockHandler.responseTime || 50);
220 | }
221 | }
222 | }
223 |
224 | // Construct a mocked XHR Object
225 | function xhr(mockHandler, requestSettings, origSettings, origHandler) {
226 | // Extend with our default mockjax settings
227 | mockHandler = $.extend(true, {}, $.mockjaxSettings, mockHandler);
228 |
229 | if (typeof mockHandler.headers === 'undefined') {
230 | mockHandler.headers = {};
231 | }
232 | if ( mockHandler.contentType ) {
233 | mockHandler.headers['content-type'] = mockHandler.contentType;
234 | }
235 |
236 | return {
237 | status: mockHandler.status,
238 | statusText: mockHandler.statusText,
239 | readyState: 1,
240 | open: function() { },
241 | send: function() {
242 | origHandler.fired = true;
243 | _xhrSend.call(this, mockHandler, requestSettings, origSettings);
244 | },
245 | abort: function() {
246 | clearTimeout(this.responseTimer);
247 | },
248 | setRequestHeader: function(header, value) {
249 | mockHandler.headers[header] = value;
250 | },
251 | getResponseHeader: function(header) {
252 | // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
253 | if ( mockHandler.headers && mockHandler.headers[header] ) {
254 | // Return arbitrary headers
255 | return mockHandler.headers[header];
256 | } else if ( header.toLowerCase() == 'last-modified' ) {
257 | return mockHandler.lastModified || (new Date()).toString();
258 | } else if ( header.toLowerCase() == 'etag' ) {
259 | return mockHandler.etag || '';
260 | } else if ( header.toLowerCase() == 'content-type' ) {
261 | return mockHandler.contentType || 'text/plain';
262 | }
263 | },
264 | getAllResponseHeaders: function() {
265 | var headers = '';
266 | $.each(mockHandler.headers, function(k, v) {
267 | headers += k + ': ' + v + "\n";
268 | });
269 | return headers;
270 | }
271 | };
272 | }
273 |
274 | // Process a JSONP mock request.
275 | function processJsonpMock( requestSettings, mockHandler, origSettings ) {
276 | // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
277 | // because there isn't an easy hook for the cross domain script tag of jsonp
278 |
279 | processJsonpUrl( requestSettings );
280 |
281 | requestSettings.dataType = "json";
282 | if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) {
283 | createJsonpCallback(requestSettings, mockHandler);
284 |
285 | // We need to make sure
286 | // that a JSONP style response is executed properly
287 |
288 | var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
289 | parts = rurl.exec( requestSettings.url ),
290 | remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
291 |
292 | requestSettings.dataType = "script";
293 | if(requestSettings.type.toUpperCase() === "GET" && remote ) {
294 | var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings );
295 |
296 | // Check if we are supposed to return a Deferred back to the mock call, or just
297 | // signal success
298 | if(newMockReturn) {
299 | return newMockReturn;
300 | } else {
301 | return true;
302 | }
303 | }
304 | }
305 | return null;
306 | }
307 |
308 | // Append the required callback parameter to the end of the request URL, for a JSONP request
309 | function processJsonpUrl( requestSettings ) {
310 | if ( requestSettings.type.toUpperCase() === "GET" ) {
311 | if ( !CALLBACK_REGEX.test( requestSettings.url ) ) {
312 | requestSettings.url += (/\?/.test( requestSettings.url ) ? "&" : "?") +
313 | (requestSettings.jsonp || "callback") + "=?";
314 | }
315 | } else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) {
316 | requestSettings.data = (requestSettings.data ? requestSettings.data + "&" : "") + (requestSettings.jsonp || "callback") + "=?";
317 | }
318 | }
319 |
320 | // Process a JSONP request by evaluating the mocked response text
321 | function processJsonpRequest( requestSettings, mockHandler, origSettings ) {
322 | // Synthesize the mock request for adding a script tag
323 | var callbackContext = origSettings && origSettings.context || requestSettings,
324 | newMock = null;
325 |
326 |
327 | // If the response handler on the moock is a function, call it
328 | if ( mockHandler.response && $.isFunction(mockHandler.response) ) {
329 | mockHandler.response(origSettings);
330 | } else {
331 |
332 | // Evaluate the responseText javascript in a global context
333 | if( typeof mockHandler.responseText === 'object' ) {
334 | $.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
335 | } else {
336 | $.globalEval( '(' + mockHandler.responseText + ')');
337 | }
338 | }
339 |
340 | // Successful response
341 | jsonpSuccess( requestSettings, mockHandler );
342 | jsonpComplete( requestSettings, mockHandler );
343 |
344 | // If we are running under jQuery 1.5+, return a deferred object
345 | if($.Deferred){
346 | newMock = new $.Deferred();
347 | if(typeof mockHandler.responseText == "object"){
348 | newMock.resolveWith( callbackContext, [mockHandler.responseText] );
349 | }
350 | else{
351 | newMock.resolveWith( callbackContext, [$.parseJSON( mockHandler.responseText )] );
352 | }
353 | }
354 | return newMock;
355 | }
356 |
357 |
358 | // Create the required JSONP callback function for the request
359 | function createJsonpCallback( requestSettings, mockHandler ) {
360 | jsonp = requestSettings.jsonpCallback || ("jsonp" + jsc++);
361 |
362 | // Replace the =? sequence both in the query string and the data
363 | if ( requestSettings.data ) {
364 | requestSettings.data = (requestSettings.data + "").replace(CALLBACK_REGEX, "=" + jsonp + "$1");
365 | }
366 |
367 | requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, "=" + jsonp + "$1");
368 |
369 |
370 | // Handle JSONP-style loading
371 | window[ jsonp ] = window[ jsonp ] || function( tmp ) {
372 | data = tmp;
373 | jsonpSuccess( requestSettings, mockHandler );
374 | jsonpComplete( requestSettings, mockHandler );
375 | // Garbage collect
376 | window[ jsonp ] = undefined;
377 |
378 | try {
379 | delete window[ jsonp ];
380 | } catch(e) {}
381 |
382 | if ( head ) {
383 | head.removeChild( script );
384 | }
385 | };
386 | }
387 |
388 | // The JSONP request was successful
389 | function jsonpSuccess(requestSettings, mockHandler) {
390 | // If a local callback was specified, fire it and pass it the data
391 | if ( requestSettings.success ) {
392 | requestSettings.success.call( callbackContext, ( mockHandler.response ? mockHandler.response.toString() : mockHandler.responseText || ''), status, {} );
393 | }
394 |
395 | // Fire the global callback
396 | if ( requestSettings.global ) {
397 | trigger(requestSettings, "ajaxSuccess", [{}, requestSettings] );
398 | }
399 | }
400 |
401 | // The JSONP request was completed
402 | function jsonpComplete(requestSettings, mockHandler) {
403 | // Process result
404 | if ( requestSettings.complete ) {
405 | requestSettings.complete.call( callbackContext, {} , status );
406 | }
407 |
408 | // The request was completed
409 | if ( requestSettings.global ) {
410 | trigger( "ajaxComplete", [{}, requestSettings] );
411 | }
412 |
413 | // Handle the global AJAX counter
414 | if ( requestSettings.global && ! --$.active ) {
415 | $.event.trigger( "ajaxStop" );
416 | }
417 | }
418 |
419 |
420 | // The core $.ajax replacement.
421 | function handleAjax( url, origSettings ) {
422 | var mockRequest, requestSettings, mockHandler;
423 |
424 | // If url is an object, simulate pre-1.5 signature
425 | if ( typeof url === "object" ) {
426 | origSettings = url;
427 | url = undefined;
428 | } else {
429 | // work around to support 1.5 signature
430 | origSettings.url = url;
431 | }
432 |
433 | // Extend the original settings for the request
434 | requestSettings = $.extend(true, {}, $.ajaxSettings, origSettings);
435 |
436 | // Iterate over our mock handlers (in registration order) until we find
437 | // one that is willing to intercept the request
438 | for(var k = 0; k < mockHandlers.length; k++) {
439 | if ( !mockHandlers[k] ) {
440 | continue;
441 | }
442 |
443 | mockHandler = getMockForRequest( mockHandlers[k], requestSettings );
444 | if(!mockHandler) {
445 | // No valid mock found for this request
446 | continue;
447 | }
448 |
449 | // Handle console logging
450 | logMock( mockHandler, requestSettings );
451 |
452 |
453 | if ( requestSettings.dataType === "jsonp" ) {
454 | if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) {
455 | // This mock will handle the JSONP request
456 | return mockRequest;
457 | }
458 | }
459 |
460 |
461 | // Removed to fix #54 - keep the mocking data object intact
462 | //mockHandler.data = requestSettings.data;
463 |
464 | mockHandler.cache = requestSettings.cache;
465 | mockHandler.timeout = requestSettings.timeout;
466 | mockHandler.global = requestSettings.global;
467 |
468 | copyUrlParameters(mockHandler, origSettings);
469 |
470 | (function(mockHandler, requestSettings, origSettings, origHandler) {
471 | mockRequest = _ajax.call($, $.extend(true, {}, origSettings, {
472 | // Mock the XHR object
473 | xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ) }
474 | }));
475 | })(mockHandler, requestSettings, origSettings, mockHandlers[k]);
476 |
477 | return mockRequest;
478 | }
479 |
480 | // We don't have a mock request, trigger a normal request
481 | return _ajax.apply($, [origSettings]);
482 | }
483 |
484 | /**
485 | * Copies URL parameter values if they were captured by a regular expression
486 | * @param {Object} mockHandler
487 | * @param {Object} origSettings
488 | */
489 | function copyUrlParameters(mockHandler, origSettings) {
490 | //parameters aren't captured if the URL isn't a RegExp
491 | if (!mockHandler.url instanceof RegExp) {
492 | return;
493 | }
494 | //if no URL params were defined on the handler, don't attempt a capture
495 | if (!mockHandler.hasOwnProperty('urlParams')) {
496 | return;
497 | }
498 | var captures = mockHandler.url.exec(origSettings.url);
499 | //the whole RegExp match is always the first value in the capture results
500 | if (captures.length === 1) {
501 | return;
502 | }
503 | captures.shift();
504 | //use handler params as keys and capture resuts as values
505 | var i = 0,
506 | capturesLength = captures.length,
507 | paramsLength = mockHandler.urlParams.length,
508 | //in case the number of params specified is less than actual captures
509 | maxIterations = Math.min(capturesLength, paramsLength),
510 | paramValues = {};
511 | for (i; i < maxIterations; i++) {
512 | var key = mockHandler.urlParams[i];
513 | paramValues[key] = captures[i];
514 | }
515 | origSettings.urlParams = paramValues;
516 | }
517 |
518 |
519 | // Public
520 |
521 | $.extend({
522 | ajax: handleAjax
523 | });
524 |
525 | $.mockjaxSettings = {
526 | //url: null,
527 | //type: 'GET',
528 | log: function( msg ) {
529 | if (window['console'] && window.console.log) {
530 | var log = Function.prototype.bind.call(console.log, console);
531 | log.apply(console, arguments);
532 | }
533 | },
534 | status: 200,
535 | statusText: "OK",
536 | responseTime: 500,
537 | isTimeout: false,
538 | contentType: 'text/plain',
539 | response: '',
540 | responseText: '',
541 | responseXML: '',
542 | proxy: '',
543 | proxyType: 'GET',
544 |
545 | lastModified: null,
546 | etag: '',
547 | headers: {
548 | etag: 'IJF@H#@923uf8023hFO@I#H#',
549 | 'content-type' : 'text/plain'
550 | }
551 | };
552 |
553 | $.mockjax = function(settings) {
554 | var i = mockHandlers.length;
555 | mockHandlers[i] = settings;
556 | return i;
557 | };
558 | $.mockjaxClear = function(i) {
559 | if ( arguments.length == 1 ) {
560 | mockHandlers[i] = null;
561 | } else {
562 | mockHandlers = [];
563 | }
564 | };
565 | $.mockjax.handler = function(i) {
566 | if ( arguments.length == 1 ) {
567 | return mockHandlers[i];
568 | }
569 | };
570 | })(jQuery);
--------------------------------------------------------------------------------
/js/specs/sinon.js:
--------------------------------------------------------------------------------
1 | /*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
2 | /*global module, require, __dirname, document*/
3 | /**
4 | * Sinon core utilities. For internal use only.
5 | *
6 | * @author Christian Johansen (christian@cjohansen.no)
7 | * @license BSD
8 | *
9 | * Copyright (c) 2010-2011 Christian Johansen
10 | */
11 | "use strict";
12 |
13 | var sinon = (function (buster) {
14 | var div = typeof document != "undefined" && document.createElement("div");
15 | var hasOwn = Object.prototype.hasOwnProperty;
16 |
17 | function isDOMNode(obj) {
18 | var success = false;
19 |
20 | try {
21 | obj.appendChild(div);
22 | success = div.parentNode == obj;
23 | } catch (e) {
24 | return false;
25 | } finally {
26 | try {
27 | obj.removeChild(div);
28 | } catch (e) {
29 | // Remove failed, not much we can do about that
30 | }
31 | }
32 |
33 | return success;
34 | }
35 |
36 | function isElement(obj) {
37 | return div && obj && obj.nodeType === 1 && isDOMNode(obj);
38 | }
39 |
40 | function isFunction(obj) {
41 | return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
42 | }
43 |
44 | function mirrorProperties(target, source) {
45 | for (var prop in source) {
46 | if (!hasOwn.call(target, prop)) {
47 | target[prop] = source[prop];
48 | }
49 | }
50 | }
51 |
52 | var sinon = {
53 | wrapMethod: function wrapMethod(object, property, method) {
54 | if (!object) {
55 | throw new TypeError("Should wrap property of object");
56 | }
57 |
58 | if (typeof method != "function") {
59 | throw new TypeError("Method wrapper should be function");
60 | }
61 |
62 | var wrappedMethod = object[property];
63 |
64 | if (!isFunction(wrappedMethod)) {
65 | throw new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
66 | property + " as function");
67 | }
68 |
69 | if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
70 | throw new TypeError("Attempted to wrap " + property + " which is already wrapped");
71 | }
72 |
73 | if (wrappedMethod.calledBefore) {
74 | var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
75 | throw new TypeError("Attempted to wrap " + property + " which is already " + verb);
76 | }
77 |
78 | // IE 8 does not support hasOwnProperty on the window object.
79 | var owned = hasOwn.call(object, property);
80 | object[property] = method;
81 | method.displayName = property;
82 |
83 | method.restore = function () {
84 | // For prototype properties try to reset by delete first.
85 | // If this fails (ex: localStorage on mobile safari) then force a reset
86 | // via direct assignment.
87 | if (!owned) {
88 | delete object[property];
89 | }
90 | if (object[property] === method) {
91 | object[property] = wrappedMethod;
92 | }
93 | };
94 |
95 | method.restore.sinon = true;
96 | mirrorProperties(method, wrappedMethod);
97 |
98 | return method;
99 | },
100 |
101 | extend: function extend(target) {
102 | for (var i = 1, l = arguments.length; i < l; i += 1) {
103 | for (var prop in arguments[i]) {
104 | if (arguments[i].hasOwnProperty(prop)) {
105 | target[prop] = arguments[i][prop];
106 | }
107 |
108 | // DONT ENUM bug, only care about toString
109 | if (arguments[i].hasOwnProperty("toString") &&
110 | arguments[i].toString != target.toString) {
111 | target.toString = arguments[i].toString;
112 | }
113 | }
114 | }
115 |
116 | return target;
117 | },
118 |
119 | create: function create(proto) {
120 | var F = function () {};
121 | F.prototype = proto;
122 | return new F();
123 | },
124 |
125 | deepEqual: function deepEqual(a, b) {
126 | if (sinon.match && sinon.match.isMatcher(a)) {
127 | return a.test(b);
128 | }
129 | if (typeof a != "object" || typeof b != "object") {
130 | return a === b;
131 | }
132 |
133 | if (isElement(a) || isElement(b)) {
134 | return a === b;
135 | }
136 |
137 | if (a === b) {
138 | return true;
139 | }
140 |
141 | if ((a === null && b !== null) || (a !== null && b === null)) {
142 | return false;
143 | }
144 |
145 | var aString = Object.prototype.toString.call(a);
146 | if (aString != Object.prototype.toString.call(b)) {
147 | return false;
148 | }
149 |
150 | if (aString == "[object Array]") {
151 | if (a.length !== b.length) {
152 | return false;
153 | }
154 |
155 | for (var i = 0, l = a.length; i < l; i += 1) {
156 | if (!deepEqual(a[i], b[i])) {
157 | return false;
158 | }
159 | }
160 |
161 | return true;
162 | }
163 |
164 | var prop, aLength = 0, bLength = 0;
165 |
166 | for (prop in a) {
167 | aLength += 1;
168 |
169 | if (!deepEqual(a[prop], b[prop])) {
170 | return false;
171 | }
172 | }
173 |
174 | for (prop in b) {
175 | bLength += 1;
176 | }
177 |
178 | if (aLength != bLength) {
179 | return false;
180 | }
181 |
182 | return true;
183 | },
184 |
185 | functionName: function functionName(func) {
186 | var name = func.displayName || func.name;
187 |
188 | // Use function decomposition as a last resort to get function
189 | // name. Does not rely on function decomposition to work - if it
190 | // doesn't debugging will be slightly less informative
191 | // (i.e. toString will say 'spy' rather than 'myFunc').
192 | if (!name) {
193 | var matches = func.toString().match(/function ([^\s\(]+)/);
194 | name = matches && matches[1];
195 | }
196 |
197 | return name;
198 | },
199 |
200 | functionToString: function toString() {
201 | if (this.getCall && this.callCount) {
202 | var thisValue, prop, i = this.callCount;
203 |
204 | while (i--) {
205 | thisValue = this.getCall(i).thisValue;
206 |
207 | for (prop in thisValue) {
208 | if (thisValue[prop] === this) {
209 | return prop;
210 | }
211 | }
212 | }
213 | }
214 |
215 | return this.displayName || "sinon fake";
216 | },
217 |
218 | getConfig: function (custom) {
219 | var config = {};
220 | custom = custom || {};
221 | var defaults = sinon.defaultConfig;
222 |
223 | for (var prop in defaults) {
224 | if (defaults.hasOwnProperty(prop)) {
225 | config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
226 | }
227 | }
228 |
229 | return config;
230 | },
231 |
232 | format: function (val) {
233 | return "" + val;
234 | },
235 |
236 | defaultConfig: {
237 | injectIntoThis: true,
238 | injectInto: null,
239 | properties: ["spy", "stub", "mock", "clock", "server", "requests"],
240 | useFakeTimers: true,
241 | useFakeServer: true
242 | },
243 |
244 | timesInWords: function timesInWords(count) {
245 | return count == 1 && "once" ||
246 | count == 2 && "twice" ||
247 | count == 3 && "thrice" ||
248 | (count || 0) + " times";
249 | },
250 |
251 | calledInOrder: function (spies) {
252 | for (var i = 1, l = spies.length; i < l; i++) {
253 | if (!spies[i - 1].calledBefore(spies[i])) {
254 | return false;
255 | }
256 | }
257 |
258 | return true;
259 | },
260 |
261 | orderByFirstCall: function (spies) {
262 | return spies.sort(function (a, b) {
263 | // uuid, won't ever be equal
264 | var aCall = a.getCall(0);
265 | var bCall = b.getCall(0);
266 | var aId = aCall && aCall.callId || -1;
267 | var bId = bCall && bCall.callId || -1;
268 |
269 | return aId < bId ? -1 : 1;
270 | });
271 | },
272 |
273 | log: function () {},
274 |
275 | logError: function (label, err) {
276 | var msg = label + " threw exception: "
277 | sinon.log(msg + "[" + err.name + "] " + err.message);
278 | if (err.stack) { sinon.log(err.stack); }
279 |
280 | setTimeout(function () {
281 | err.message = msg + err.message;
282 | throw err;
283 | }, 0);
284 | },
285 |
286 | typeOf: function (value) {
287 | if (value === null) {
288 | return "null";
289 | }
290 | else if (value === undefined) {
291 | return "undefined";
292 | }
293 | var string = Object.prototype.toString.call(value);
294 | return string.substring(8, string.length - 1).toLowerCase();
295 | },
296 |
297 | createStubInstance: function (constructor) {
298 | if (typeof constructor !== "function") {
299 | throw new TypeError("The constructor should be a function.");
300 | }
301 | return sinon.stub(sinon.create(constructor.prototype));
302 | }
303 | };
304 |
305 | var isNode = typeof module == "object" && typeof require == "function";
306 |
307 | if (isNode) {
308 | try {
309 | buster = { format: require("buster-format") };
310 | } catch (e) {}
311 | module.exports = sinon;
312 | module.exports.spy = require("./sinon/spy");
313 | module.exports.stub = require("./sinon/stub");
314 | module.exports.mock = require("./sinon/mock");
315 | module.exports.collection = require("./sinon/collection");
316 | module.exports.assert = require("./sinon/assert");
317 | module.exports.sandbox = require("./sinon/sandbox");
318 | module.exports.test = require("./sinon/test");
319 | module.exports.testCase = require("./sinon/test_case");
320 | module.exports.assert = require("./sinon/assert");
321 | module.exports.match = require("./sinon/match");
322 | }
323 |
324 | if (buster) {
325 | var formatter = sinon.create(buster.format);
326 | formatter.quoteStrings = false;
327 | sinon.format = function () {
328 | return formatter.ascii.apply(formatter, arguments);
329 | };
330 | } else if (isNode) {
331 | try {
332 | var util = require("util");
333 | sinon.format = function (value) {
334 | return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
335 | };
336 | } catch (e) {
337 | /* Node, but no util module - would be very old, but better safe than
338 | sorry */
339 | }
340 | }
341 |
342 | return sinon;
343 | }(typeof buster == "object" && buster));
344 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Chris Love
2 |
3 | http://deeptissuejs.com
4 | https://github.com/docluv/deeptissuejs
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7 |
8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 |
10 | 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.
11 |
--------------------------------------------------------------------------------
/msTouchIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/docluv/deeptissuejs/2455e8f32e198939fdb2266a2616606a2ac547f3/msTouchIcon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deeptissuejs",
3 | "version": "0.0.4",
4 | "devDependencies": {
5 | "grunt" : "~0.4.*",
6 | "grunt-contrib-cssmin": "*",
7 | "grunt-contrib-qunit": "*",
8 | "grunt-contrib-jshint": "*",
9 | "grunt-contrib-uglify": "*",
10 | "grunt-contrib-concat": "*",
11 | "grunt-contrib-watch": "*",
12 | "grunt-bump": "*",
13 | "matchdep": "*"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/qunit.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Deep Tissue Unit Tests
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
44 |
45 |
46 |
47 |
48 |
49 | QUnit tests
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
69 |
70 |
71 |
72 |
73 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # [Deeptissue.js](https://deeptissuejs.com/)
2 |
3 | **** NOTE ****
4 |
5 | Apple seems to have finally caught up to the rest of the web on touch events, at least on iOS. As of iOS 13 Safari now seems to have support for Pointer Events.
6 |
7 | As soon as I have time to test and verify this I will update.
8 |
9 | So hopefully, like many other library floating around the web I can deprecate this library in favor os native functionality. :)
10 |
11 | ****
12 |
13 | Deeptissue.js is a helper library to abstract away the differences between the MSPointer
14 | and WebKit Touch APIs. There are many JavaScript libraries publicly available that support
15 | the WebKit API and a few that help with the MSPointer API, but I reand nothing that bridged
16 | the gap. So I decided I would create a library to do just that.
17 |
18 | * Source: [https://github.com/docluv/deeptissuejs](https://github.com/docluv/deeptissuejs)
19 | * Homepage: [http://deeptissuejs.com](http://deeptissuejs.com)
20 | * Twitter: [@ChrisLove](http://twitter.com/ChrisLove)
21 |
22 | ## Quick start
23 |
24 | Clone the git repo - `git clone git://github.com/docluv/deeptissuejs.git` -
25 | or [download it](https:////github.com/docluv/deeptissuejs/deeptissue.min.js)
26 |
27 |
28 | ## Features
29 |
30 | * Abstracts MSPointer and WebKit Touch APIs.
31 | * Supports
32 | * tap, double-tap, tap-hold,
33 | * move, horizontal-move, vertical-move,
34 | * swipe left, swipe right, swipe up, swipe down,
35 | * Rotate and Scale for IE10 and Mobile Safari
36 |
37 | ## Documentation
38 |
39 | Take a look at the [documentation table of contents](doc/README.md). This
40 | documentation is bundled with the project, which makes it readily available for
41 | offline reading and provides a useful starting point for any documentation you
42 | want to write about your project.
43 |
44 |
--------------------------------------------------------------------------------
/realgesturechangetest.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Deep Tissue Real Tests
6 |
7 |
8 |
62 |
63 |
64 |
65 |