pinstripe 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.pinstripe +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +24 -0
- data/LICENSE +20 -0
- data/README.md +5 -0
- data/Rakefile +10 -0
- data/exe/pinstripe +4 -0
- data/lib/pinstripe/call_handler.rb +12 -0
- data/lib/pinstripe/command.rb +20 -0
- data/lib/pinstripe/commands/list_commands.rb +16 -0
- data/lib/pinstripe/commands/start_console.rb +14 -0
- data/lib/pinstripe/concern.rb +19 -0
- data/lib/pinstripe/database/row.rb +48 -0
- data/lib/pinstripe/database/table.rb +131 -0
- data/lib/pinstripe/database/table_alias_manager.rb +20 -0
- data/lib/pinstripe/database/union.rb +20 -0
- data/lib/pinstripe/database.rb +56 -0
- data/lib/pinstripe/helper.rb +20 -0
- data/lib/pinstripe/helpers.rb +8 -0
- data/lib/pinstripe/inflector/inflections.rb +122 -0
- data/lib/pinstripe/inflector.rb +28 -0
- data/lib/pinstripe/monkey_patches/pluralize.rb +8 -0
- data/lib/pinstripe/monkey_patches/require_all.rb +18 -0
- data/lib/pinstripe/monkey_patches/singularize.rb +8 -0
- data/lib/pinstripe/monkey_patches/to_params_hash.rb +20 -0
- data/lib/pinstripe/params_hash.rb +44 -0
- data/lib/pinstripe/project.rb +29 -0
- data/lib/pinstripe/registry.rb +46 -0
- data/lib/pinstripe/resource_factories/call_handler.rb +8 -0
- data/lib/pinstripe/resource_factories/env.rb +9 -0
- data/lib/pinstripe/resource_factories/environment.rb +8 -0
- data/lib/pinstripe/resource_factories/project.rb +8 -0
- data/lib/pinstripe/resource_factory.rb +32 -0
- data/lib/pinstripe/resource_provider.rb +50 -0
- data/lib/pinstripe/version.rb +3 -0
- data/lib/pinstripe/workspace.rb +8 -0
- data/lib/pinstripe.rb +24 -0
- data/package.json +15 -0
- data/pinstripe +4 -0
- data/pinstripe.gemspec +38 -0
- data/rollup.config.js +19 -0
- data/web/javascripts/_pinstripe/event_wrapper.js +29 -0
- data/web/javascripts/_pinstripe/index.js +3 -0
- data/web/javascripts/_pinstripe/initialize.js +29 -0
- data/web/javascripts/_pinstripe/node_wrapper.js +354 -0
- data/web/javascripts/_pinstripe/node_wrappers/anchor.js +56 -0
- data/web/javascripts/_pinstripe/node_wrappers/document.js +27 -0
- data/web/javascripts/_pinstripe/node_wrappers/form.js +52 -0
- data/web/javascripts/_pinstripe/node_wrappers/frame.js +72 -0
- data/web/javascripts/_pinstripe/node_wrappers/index.js +8 -0
- data/web/javascripts/_pinstripe/node_wrappers/input.js +23 -0
- data/web/javascripts/_pinstripe/node_wrappers/modal.js +36 -0
- data/web/javascripts/_pinstripe/node_wrappers/script.js +17 -0
- data/web/javascripts/_pinstripe/string_reader.js +24 -0
- data/web/javascripts/_pinstripe/url.js +94 -0
- data/web/javascripts/_pinstripe/util/benchmark.js +10 -0
- data/web/javascripts/_pinstripe/util/capitalize.js +4 -0
- data/web/javascripts/_pinstripe/util/index.js +4 -0
- data/web/javascripts/_pinstripe/util/unescape_html.js +13 -0
- data/web/javascripts/_pinstripe/virtual_node.js +156 -0
- data/yarn.lock +72 -0
- metadata +162 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
|
|
2
|
+
import { capitalize } from './util'
|
|
3
|
+
import { VirtualNode } from './virtual_node'
|
|
4
|
+
import { EventWrapper } from './event_wrapper'
|
|
5
|
+
|
|
6
|
+
const nodeWrappers = [];
|
|
7
|
+
|
|
8
|
+
export class NodeWrapper {
|
|
9
|
+
|
|
10
|
+
static get selector(){ return `.${this.name}` }
|
|
11
|
+
|
|
12
|
+
static register(){
|
|
13
|
+
const klass = this
|
|
14
|
+
|
|
15
|
+
nodeWrappers.unshift(klass)
|
|
16
|
+
|
|
17
|
+
Object.defineProperty(NodeWrapper.prototype, klass.name, {
|
|
18
|
+
get: function(){
|
|
19
|
+
let current = this.parent
|
|
20
|
+
while(current){
|
|
21
|
+
if(current instanceof klass){
|
|
22
|
+
return current
|
|
23
|
+
}
|
|
24
|
+
current = current.parent
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
Object.defineProperty(NodeWrapper.prototype, `is${capitalize(klass.name)}`, {
|
|
30
|
+
get: function(){
|
|
31
|
+
return this instanceof klass
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static instanceFor(node){
|
|
37
|
+
if(!node.$p){
|
|
38
|
+
node.$p = new NodeWrapper(node)
|
|
39
|
+
nodeWrappers.some((klass) => {
|
|
40
|
+
if(node.$p.is(klass.selector)){
|
|
41
|
+
node.$p = new klass(node)
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
return node.$p
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
constructor(node){
|
|
50
|
+
this.node = node
|
|
51
|
+
this.$registeredEventListeners = []
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
get type(){
|
|
56
|
+
return this.node instanceof DocumentType ? '#doctype' : this.node.nodeName.toLowerCase()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get attributes(){
|
|
60
|
+
const out = {}
|
|
61
|
+
if(this.node.attributes){
|
|
62
|
+
for(let i = 0; i < this.node.attributes.length; i++){
|
|
63
|
+
out[this.node.attributes[i].name] = this.node.attributes[i].value
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return out
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get text(){
|
|
70
|
+
return this.node.textContent
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get realParent(){
|
|
74
|
+
return this.node.parentNode ? this.constructor.instanceFor(this.node.parentNode) : null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get parent(){
|
|
78
|
+
if(this.$parent){
|
|
79
|
+
return this.$parent
|
|
80
|
+
}
|
|
81
|
+
return this.realParent
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get parents(){
|
|
85
|
+
const out = []
|
|
86
|
+
let current = this
|
|
87
|
+
while(current.parent){
|
|
88
|
+
current = current.parent
|
|
89
|
+
out.push(parent)
|
|
90
|
+
}
|
|
91
|
+
return out
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get children(){
|
|
95
|
+
return [...this.node.childNodes].map(
|
|
96
|
+
node => this.constructor.instanceFor(node)
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get siblings(){
|
|
101
|
+
if(this.parent){
|
|
102
|
+
return this.parent.children
|
|
103
|
+
} else {
|
|
104
|
+
return [this]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
get previousSibling(){
|
|
109
|
+
if(this.node.previousSibling){
|
|
110
|
+
return this.constructor.instanceFor(this.node.previousSibling)
|
|
111
|
+
} else {
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
get nextSibling(){
|
|
117
|
+
if(this.node.nextSibling){
|
|
118
|
+
return this.constructor.instanceFor(this.node.nextSibling)
|
|
119
|
+
} else {
|
|
120
|
+
return null
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
get nextSiblings(){
|
|
125
|
+
const out = []
|
|
126
|
+
let current = this
|
|
127
|
+
while(current.nextSibling){
|
|
128
|
+
current = current.nextSibling
|
|
129
|
+
out.push(current)
|
|
130
|
+
}
|
|
131
|
+
return out
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
get previousSiblings(){
|
|
135
|
+
const out = []
|
|
136
|
+
let current = this
|
|
137
|
+
while(current.previousSibling){
|
|
138
|
+
current = current.previousSibling
|
|
139
|
+
out.push(current)
|
|
140
|
+
}
|
|
141
|
+
return out
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
get descendants(){
|
|
145
|
+
return this.find(() => true)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
find(selector, out = []){
|
|
149
|
+
this.children.forEach((child) => {
|
|
150
|
+
if(child.is(selector)){
|
|
151
|
+
out.push(child)
|
|
152
|
+
}
|
|
153
|
+
child.find(selector, out)
|
|
154
|
+
})
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
is(selector){
|
|
159
|
+
if(typeof selector == 'function'){
|
|
160
|
+
return selector.call(this, this)
|
|
161
|
+
}
|
|
162
|
+
return (this.node.matches || this.node.matchesSelector || this.node.msMatchesSelector || this.node.mozMatchesSelector || this.node.webkitMatchesSelector || this.node.oMatchesSelector || (() => false)).call(this.node, selector)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
on(name, ...args){
|
|
166
|
+
const fn = args.pop()
|
|
167
|
+
const selector = args.pop()
|
|
168
|
+
|
|
169
|
+
const wrapperFn = (event, ...args) => {
|
|
170
|
+
const eventWrapper = EventWrapper.instanceFor(event)
|
|
171
|
+
if(selector){
|
|
172
|
+
if(eventWrapper.target.is(selector)){
|
|
173
|
+
return fn.call(eventWrapper.target, eventWrapper, ...args)
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
return fn.call(this, eventWrapper, ...args)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
this.node.addEventListener(name, wrapperFn)
|
|
181
|
+
|
|
182
|
+
this.$registeredEventListeners.push([name, wrapperFn])
|
|
183
|
+
|
|
184
|
+
return this
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
trigger(name, data){
|
|
188
|
+
if (window.CustomEvent && typeof window.CustomEvent === 'function') {
|
|
189
|
+
var event = new CustomEvent(name, { bubbles: true, cancelable: true, detail: data } );
|
|
190
|
+
} else {
|
|
191
|
+
var event = document.createEvent('CustomEvent')
|
|
192
|
+
event.initCustomEvent(name, true, true, data)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
this.node.dispatchEvent(event)
|
|
196
|
+
|
|
197
|
+
return this
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
remove(){
|
|
201
|
+
if(this.type != '#doctype'){
|
|
202
|
+
this.realParent.node.removeChild(this.node)
|
|
203
|
+
}
|
|
204
|
+
return this
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
addClass(name){
|
|
208
|
+
this.node.classList.add(name)
|
|
209
|
+
return this
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
removeClass(name){
|
|
213
|
+
this.node.classList.remove(name)
|
|
214
|
+
return this
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
patch(html){
|
|
218
|
+
cleanChildren.call(this)
|
|
219
|
+
patchChildren.call(this, VirtualNode.fromString(html).children)
|
|
220
|
+
initChildren.call(this)
|
|
221
|
+
return this.children
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
append(html){
|
|
225
|
+
return prepend.call(this, html)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
prepend(html){
|
|
229
|
+
return prepend.call(this, html, this.children[0])
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
insertBefore(html){
|
|
233
|
+
return prepend.call(this.realParent, html, this)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
insertAfter(html){
|
|
237
|
+
return prepend.call(this.realParent, html, this.nextSibling)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function cleanChildren(){
|
|
243
|
+
this.children.forEach(child => clean.call(child))
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function clean(){
|
|
247
|
+
[...this.node.childNodes].forEach(node => node.$p && clean.call(node.$p))
|
|
248
|
+
|
|
249
|
+
while(this.$registeredEventListeners.length){
|
|
250
|
+
this.node.removeEventListener(...this.$registeredEventListeners.pop())
|
|
251
|
+
}
|
|
252
|
+
this.node.$p = undefined
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function initChildren(){
|
|
256
|
+
this.children.forEach(child => initChildren.call(child))
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function prepend(html, referenceChild){
|
|
260
|
+
const out = []
|
|
261
|
+
VirtualNode.fromString(html).children.forEach((virtualChild) => {
|
|
262
|
+
out.push(insert.call(this, virtualChild, referenceChild))
|
|
263
|
+
})
|
|
264
|
+
return out
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function patch(attributes, virtualChildren){
|
|
268
|
+
patchAttributes.call(this, attributes)
|
|
269
|
+
patchChildren.call(this, virtualChildren)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function patchAttributes(attributes){
|
|
273
|
+
if(this.type == '#text' || this.type == '#comment'){
|
|
274
|
+
if(this.node.textContent != attributes.value){
|
|
275
|
+
this.node.textContent = attributes.value
|
|
276
|
+
}
|
|
277
|
+
} else if(this.type != '#doctype'){
|
|
278
|
+
const currentAttributes = this.attributes
|
|
279
|
+
Object.keys(currentAttributes).forEach((key) => {
|
|
280
|
+
if(attributes[key] === undefined){
|
|
281
|
+
this.node.removeAttribute(key)
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
Object.keys(attributes).forEach((key) => {
|
|
285
|
+
if(currentAttributes[key] != attributes[key]){
|
|
286
|
+
this.node.setAttribute(key, attributes[key])
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function patchChildren(virtualChildren){
|
|
293
|
+
const children = [...this.node.childNodes].map(
|
|
294
|
+
node => new NodeWrapper(node)
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
for(let i = 0; i < virtualChildren.length; i++){
|
|
298
|
+
let child = children[0]
|
|
299
|
+
const virtualChild = virtualChildren[i]
|
|
300
|
+
|
|
301
|
+
if(child && child.type == virtualChild.type){
|
|
302
|
+
patch.call(children.shift(), virtualChild.attributes, virtualChild.children)
|
|
303
|
+
} else if(virtualChild.type == '#doctype'){
|
|
304
|
+
// ignore
|
|
305
|
+
} else if(virtualChild.type.match(/^#(text|comment)/)){
|
|
306
|
+
insert.call(this, virtualChild, child)
|
|
307
|
+
} else {
|
|
308
|
+
while(children.length > 0 && children[0].type.match(/^#/)){
|
|
309
|
+
children.shift().remove()
|
|
310
|
+
}
|
|
311
|
+
child = children[0]
|
|
312
|
+
if(child && child.type == virtualChild.type){
|
|
313
|
+
patch.call(children.shift(), virtualChild.attributes, virtualChild.children);
|
|
314
|
+
} else {
|
|
315
|
+
insert.call(this, virtualChild, child)
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
while(children.length > 0){
|
|
321
|
+
children.shift().remove()
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function insert(virtualNode, referenceChild, returnNodeWrapper = true){
|
|
326
|
+
const { type, attributes, children } = virtualNode
|
|
327
|
+
|
|
328
|
+
let node
|
|
329
|
+
|
|
330
|
+
if(type == '#text'){
|
|
331
|
+
node = document.createTextNode(attributes.value)
|
|
332
|
+
} else if(type == '#comment'){
|
|
333
|
+
node = document.createComment(attributes.value)
|
|
334
|
+
} else {
|
|
335
|
+
node = document.createElement(type)
|
|
336
|
+
Object.keys(attributes).forEach((key) => {
|
|
337
|
+
node.setAttribute(key, attributes[key])
|
|
338
|
+
})
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
children.forEach(child => {
|
|
342
|
+
insert.call(new NodeWrapper(node), child, null, false)
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
this.node.insertBefore(
|
|
346
|
+
node,
|
|
347
|
+
referenceChild && referenceChild.node
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
if(returnNodeWrapper){
|
|
351
|
+
return NodeWrapper.instanceFor(node)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
|
|
2
|
+
import { NodeWrapper } from '../node_wrapper'
|
|
3
|
+
import { Url } from '../url'
|
|
4
|
+
|
|
5
|
+
export class Anchor extends NodeWrapper {
|
|
6
|
+
|
|
7
|
+
static get name(){ return 'anchor' }
|
|
8
|
+
|
|
9
|
+
static get selector(){ return 'a, .anchor' }
|
|
10
|
+
|
|
11
|
+
constructor(...args){
|
|
12
|
+
super(...args)
|
|
13
|
+
|
|
14
|
+
this.on('click', (event) => {
|
|
15
|
+
if(this.url.host == this.frame.url.host && this.url.port == this.frame.url.port){
|
|
16
|
+
event.preventDefault()
|
|
17
|
+
|
|
18
|
+
const confirm = this.attributes['data-confirm']
|
|
19
|
+
const method = this.attributes['data-method'] || 'GET'
|
|
20
|
+
const target = this.attributes['target'] || this.attributes['data-target'] || '_top'
|
|
21
|
+
|
|
22
|
+
if(!confirm || window.confirm(confirm)){
|
|
23
|
+
if(target == '_modal'){
|
|
24
|
+
this.document.find('html').pop().addClass('is-clipped')
|
|
25
|
+
this.document.find('body').pop().append(`<div class="modal is-active" data-url="${this.url}"></div>`).forEach((modal) => {
|
|
26
|
+
modal.$parent = this
|
|
27
|
+
modal.load({})
|
|
28
|
+
})
|
|
29
|
+
} else {
|
|
30
|
+
this.frame.load({ $method: method, $url: this.url })
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get url(){
|
|
38
|
+
if(this.$url === undefined){
|
|
39
|
+
this.$url = Url.fromString(
|
|
40
|
+
this.attributes['href'] || this.attributes['data-url'],
|
|
41
|
+
this.frame.url
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
return this.$url
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
set url(url){
|
|
48
|
+
this.$url = Url.fromString(
|
|
49
|
+
url,
|
|
50
|
+
this.url
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Anchor.register()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Frame } from './frame'
|
|
2
|
+
|
|
3
|
+
export class Document extends Frame {
|
|
4
|
+
|
|
5
|
+
static get name(){ return 'document' }
|
|
6
|
+
|
|
7
|
+
static get selector(){ return function(){ return this.type == '#document' } }
|
|
8
|
+
|
|
9
|
+
constructor(...args){
|
|
10
|
+
super(...args)
|
|
11
|
+
window.onpopstate = (event) => {
|
|
12
|
+
this.load({ $pushState: false, $url: event.state || window.location })
|
|
13
|
+
}
|
|
14
|
+
window.$p = this
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
load({ $pushState = true, ...params }){
|
|
18
|
+
const previousUrl = this.url.toString()
|
|
19
|
+
super.load(params)
|
|
20
|
+
if($pushState && params.$method == 'GET' && previousUrl != this.url.toString()){
|
|
21
|
+
history.pushState(this.url.toString(), null, this.url.toString())
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Document.register()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
import { NodeWrapper } from '../node_wrapper'
|
|
3
|
+
import { Url } from '../url'
|
|
4
|
+
|
|
5
|
+
export class Form extends NodeWrapper {
|
|
6
|
+
|
|
7
|
+
static get name(){ return 'form' }
|
|
8
|
+
|
|
9
|
+
static get selector(){ return 'form, .form' }
|
|
10
|
+
|
|
11
|
+
constructor(...args){
|
|
12
|
+
super(...args)
|
|
13
|
+
|
|
14
|
+
this.on('submit', (event) => {
|
|
15
|
+
console.log('Form submit', event)
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
this.frame.load({$method: this.method, $url: this.url, ...this.params })
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get method(){
|
|
22
|
+
return this.attributes['method'] || this.attributes['data-method'] || 'POST'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get url(){
|
|
26
|
+
if(this.$url === undefined){
|
|
27
|
+
this.$url = Url.fromString(
|
|
28
|
+
this.attributes['action'] || this.attributes['data-url'],
|
|
29
|
+
this.frame.url
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
return this.$url
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get inputs(){
|
|
36
|
+
return this.descendants.filter((descendant) => descendant.isInput)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get params(){
|
|
40
|
+
const out = {}
|
|
41
|
+
this.inputs.forEach(input => {
|
|
42
|
+
const value = input.value
|
|
43
|
+
if(value !== undefined){
|
|
44
|
+
out[input.name] = value
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
return out
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Form.register()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
import { NodeWrapper } from '../node_wrapper'
|
|
3
|
+
import { Url } from '../url'
|
|
4
|
+
|
|
5
|
+
export class Frame extends NodeWrapper {
|
|
6
|
+
|
|
7
|
+
static get name(){ return 'frame' }
|
|
8
|
+
|
|
9
|
+
constructor(...args){
|
|
10
|
+
super(...args)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get url(){
|
|
14
|
+
if(this.$url === undefined){
|
|
15
|
+
this.$url = Url.fromString(
|
|
16
|
+
this.attributes['data-url'] || window.location,
|
|
17
|
+
this.frame ? this.frame.url : window.location
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
return this.$url
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
set url(url){
|
|
24
|
+
this.$url = Url.fromString(
|
|
25
|
+
url,
|
|
26
|
+
this.url
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
load({$method = 'GET', $url = this.url.toString(), $headers = {}, ...params }){
|
|
31
|
+
if(this.request){
|
|
32
|
+
this.request.abort()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
$method = $method.toUpperCase();
|
|
36
|
+
|
|
37
|
+
this.url = $url
|
|
38
|
+
const isRequestBody = $method == 'POST' || $method == 'PUT' || $method == 'PATCH';
|
|
39
|
+
if(!isRequestBody){
|
|
40
|
+
this.url.params = {...this.url.params, ...params}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.request = new XMLHttpRequest();
|
|
44
|
+
|
|
45
|
+
this.request.open($method, this.url.toString(), true);
|
|
46
|
+
|
|
47
|
+
this.request.onload = () => {
|
|
48
|
+
if (this.request.status >= 200 && this.request.status < 400) {
|
|
49
|
+
this.patch(this.request.response)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const defaultHeaders = {};
|
|
54
|
+
const document = this.document || this
|
|
55
|
+
const csrfToken = document.find('meta[name="csrf-token"').map(nodeWrapper => nodeWrapper.attributes.content).pop()
|
|
56
|
+
if(csrfToken){
|
|
57
|
+
defaultHeaders['X-CSRF-Token'] = csrfToken
|
|
58
|
+
}
|
|
59
|
+
const headers = {...defaultHeaders, ...this.headers}
|
|
60
|
+
Object.keys(headers).forEach((name) => this.request.setRequestHeader(name, headers[name]))
|
|
61
|
+
|
|
62
|
+
const formData = new FormData();
|
|
63
|
+
if(isRequestBody){
|
|
64
|
+
Object.keys(params).forEach((name) => formData.append(name, params[name]));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.request.send(formData)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Frame.register()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
import { NodeWrapper } from '../node_wrapper'
|
|
3
|
+
|
|
4
|
+
export class Input extends NodeWrapper {
|
|
5
|
+
|
|
6
|
+
static get name(){ return 'input' }
|
|
7
|
+
|
|
8
|
+
static get selector(){ return 'input, textarea, .input' }
|
|
9
|
+
|
|
10
|
+
get name(){
|
|
11
|
+
return this.attributes.name
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get value(){
|
|
15
|
+
if(this.is('input[type="checkbox"], input[type="radio"]')){
|
|
16
|
+
return this.is(':checked') ? this.node.value : undefined
|
|
17
|
+
}
|
|
18
|
+
return this.node.value
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Input.register()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
import { Frame } from './frame'
|
|
3
|
+
import { NodeWrapper } from '../node_wrapper'
|
|
4
|
+
|
|
5
|
+
export class Modal extends Frame {
|
|
6
|
+
|
|
7
|
+
static get name(){ return 'modal' }
|
|
8
|
+
|
|
9
|
+
constructor(...args){
|
|
10
|
+
super(...args)
|
|
11
|
+
this.on('click', '.modal-background, .modal-close', (event) => {
|
|
12
|
+
event.stopPropagation()
|
|
13
|
+
this.close()
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
close(){
|
|
18
|
+
this.remove()
|
|
19
|
+
if(!this.document.find('body').pop().children.filter((child) => child.is('.modal')).length){
|
|
20
|
+
this.document.find('html').pop().removeClass('is-clipped')
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
patch(html){
|
|
25
|
+
return super.patch(`
|
|
26
|
+
<div class="modal-background"></div>
|
|
27
|
+
<div class="modal-content">
|
|
28
|
+
<div class="box">${html}</div>
|
|
29
|
+
</div>
|
|
30
|
+
<button class="modal-close is-large" aria-label="close"></button>
|
|
31
|
+
`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Modal.register()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
import { NodeWrapper } from '../node_wrapper'
|
|
3
|
+
|
|
4
|
+
export class Script extends NodeWrapper {
|
|
5
|
+
|
|
6
|
+
static get name(){ return 'script' }
|
|
7
|
+
|
|
8
|
+
static get selector(){ return 'script[type="pinstripe"]' }
|
|
9
|
+
|
|
10
|
+
constructor(...args){
|
|
11
|
+
super(...args)
|
|
12
|
+
eval(this.text)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Script.register()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
export class StringReader {
|
|
3
|
+
|
|
4
|
+
constructor(string){
|
|
5
|
+
this.string = (string || '').toString();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
get length(){
|
|
9
|
+
return this.string.length
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
toString(){
|
|
13
|
+
return this.string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
match(...args){
|
|
17
|
+
const out = this.string.match(...args)
|
|
18
|
+
if(out){
|
|
19
|
+
this.string = this.string.substr(out[0].length)
|
|
20
|
+
}
|
|
21
|
+
return out
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|