pinstripe 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|