lanes 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/client/lanes/Config.coffee +26 -9
  3. data/client/lanes/access/screens/user-management/UserManagement.cjsx +1 -1
  4. data/client/lanes/components/grid/EditingMixin.cjsx +8 -4
  5. data/client/lanes/components/grid/PopOverMixin.cjsx +7 -1
  6. data/client/lanes/components/modal/Modal.cjsx +11 -1
  7. data/client/lanes/components/record-finder/RecordFinder.cjsx +8 -4
  8. data/client/lanes/components/shared/DateTime.cjsx +8 -6
  9. data/client/lanes/components/shared/FieldMixin.cjsx +3 -3
  10. data/client/lanes/components/shared/Icon.cjsx +1 -1
  11. data/client/lanes/components/shared/ImageAsset.cjsx +23 -11
  12. data/client/lanes/components/shared/NetworkActivityOverlay.cjsx +2 -0
  13. data/client/lanes/extension/Base.coffee +2 -0
  14. data/client/lanes/fonts/fontawesome-webfont.woff +0 -0
  15. data/client/lanes/fonts/fontawesome-webfont.woff2 +0 -0
  16. data/client/lanes/lib/RequestAssets.coffee +30 -0
  17. data/client/lanes/lib/all.js +1 -0
  18. data/client/lanes/lib/loader.js +93 -0
  19. data/client/lanes/lib/utilFunctions.coffee +12 -0
  20. data/client/lanes/models/Asset.coffee +3 -4
  21. data/client/lanes/models/AssociationMap.coffee +17 -6
  22. data/client/lanes/models/Base.coffee +20 -13
  23. data/client/lanes/models/Collection.coffee +4 -1
  24. data/client/lanes/models/PubSub.coffee +2 -3
  25. data/client/lanes/models/SmtpSettings.coffee +7 -0
  26. data/client/lanes/models/Sync.coffee +2 -2
  27. data/client/lanes/react/Viewport.coffee +14 -10
  28. data/client/lanes/react/mixins/FieldErrors.coffee +3 -4
  29. data/client/lanes/react/mixins/ReadEditingState.coffee +1 -0
  30. data/client/lanes/remote/Bootstrap.coffee +85 -0
  31. data/client/lanes/remote/api.coffee +2 -1
  32. data/client/lanes/remote/onDocumentReady.coffee +12 -0
  33. data/client/lanes/screens/Definitions.coffee +29 -12
  34. data/client/lanes/screens/SystemSettings.cjsx +12 -3
  35. data/client/lanes/styles/fonts/_bordered-pulled.scss +9 -0
  36. data/client/lanes/styles/fonts/_core.scss +1 -2
  37. data/client/lanes/styles/fonts/_icons.scss +56 -0
  38. data/client/lanes/styles/fonts/_mixins.scss +37 -4
  39. data/client/lanes/styles/fonts/_path.scss +2 -2
  40. data/client/lanes/styles/fonts/_screen-reader.scss +5 -0
  41. data/client/lanes/styles/fonts/_variables.scss +58 -2
  42. data/client/lanes/styles/fonts/font-awesome.scss +3 -1
  43. data/client/lanes/vendor/development/calendar.js +56 -57
  44. data/client/lanes/vendor/development/commons.js +31319 -29618
  45. data/client/lanes/vendor/development/data.js +8468 -7607
  46. data/client/lanes/vendor/development/helpers.js +265 -131
  47. data/client/lanes/vendor/development/toggle.js +288 -184
  48. data/client/lanes/vendor/development/ui.js +3387 -3492
  49. data/client/lanes/vendor/development/widgets.js +972 -1229
  50. data/client/lanes/vendor/production/calendar.js +60 -61
  51. data/client/lanes/vendor/production/commons.js +30695 -29032
  52. data/client/lanes/vendor/production/data.js +8457 -7598
  53. data/client/lanes/vendor/production/toggle.js +288 -184
  54. data/client/lanes/vendor/production/ui.js +3264 -3373
  55. data/client/lanes/vendor/production/widgets.js +972 -1229
  56. data/client/lanes/vendor/standalone/index.js +21106 -18761
  57. data/client/lanes/vendor/styles/toggle.scss +4 -3
  58. data/client/lanes/workspace/ScreenView.cjsx +2 -2
  59. data/client/lanes/workspace/styles/header.scss +4 -0
  60. data/config/routes.rb +0 -2
  61. data/db/migrate/01_create_system_settings.rb +1 -1
  62. data/db/migrate/02_create_assets.rb +1 -1
  63. data/lanes.gemspec +1 -0
  64. data/lib/lanes.rb +1 -0
  65. data/lib/lanes/access/track_modifications.rb +4 -2
  66. data/lib/lanes/api.rb +1 -0
  67. data/lib/lanes/api/cable.rb +11 -3
  68. data/lib/lanes/api/controller_base.rb +23 -19
  69. data/lib/lanes/api/default_routes.rb +9 -1
  70. data/lib/lanes/api/generic_controller.rb +1 -1
  71. data/lib/lanes/api/handlers/asset.rb +2 -3
  72. data/lib/lanes/api/helper_methods.rb +5 -11
  73. data/lib/lanes/api/pub_sub.rb +13 -7
  74. data/lib/lanes/api/request_wrapper.rb +1 -1
  75. data/lib/lanes/api/routing.rb +10 -7
  76. data/lib/lanes/api/to_json.rb +7 -0
  77. data/lib/lanes/asset.rb +4 -1
  78. data/lib/lanes/concerns/set_attribute_data.rb +2 -1
  79. data/lib/lanes/extension.rb +3 -1
  80. data/lib/lanes/mailer.rb +40 -0
  81. data/lib/lanes/rake_tasks.rb +4 -0
  82. data/lib/lanes/spec_helper.rb +11 -3
  83. data/lib/lanes/system_settings.rb +22 -9
  84. data/lib/lanes/version.rb +1 -1
  85. data/lib/lanes/workspace/extension.rb +5 -0
  86. data/npm-build/package.json +2 -2
  87. data/npm-build/react-toggle.js +1 -1
  88. data/npm-build/standalone.js +3 -0
  89. data/spec/command-reference-files/initial/Gemfile +1 -1
  90. data/spec/command-reference-files/initial/client/appy-app/Extension.coffee +2 -1
  91. data/spec/command-reference-files/model/db/migrate/20150218032025_create_test_tests.rb +1 -1
  92. data/spec/command-reference-files/screen/client/appy-app/Extension.coffee +2 -1
  93. data/spec/fixtures/system_settings.yml +8 -1
  94. data/spec/server/mailer_spec.rb +33 -0
  95. data/spec/server/system_settings_spec.rb +16 -0
  96. data/templates/client/Extension.coffee +2 -1
  97. data/templates/config/database.yml +1 -1
  98. data/templates/db/create_table_migration.rb +1 -1
  99. metadata +27 -6
  100. data/client/fonts/fontawesome-webfont.woff +0 -0
  101. data/client/fonts/fontawesome-webfont.woff2 +0 -0
  102. data/client/lanes/lib/loader.coffee +0 -100
  103. data/client/lanes/workspace/Modal.cjsx +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61899d6310319e01eeb5f8d3143de6381d59ef22
4
- data.tar.gz: 7684de7e8724e81d9bb3a294dc995d3f74a7a8e5
3
+ metadata.gz: 16b8badf6014b9cc559daad0046bffa56d08e791
4
+ data.tar.gz: b0018988b0ef191d183965f06ace441c7875b073
5
5
  SHA512:
6
- metadata.gz: 6037b22dcff009ca206df7145b6058bd8b0e4403e0459f1ce0367afc63a94db7cdd700d225d9cd1c29d86e065392bb087927e71b0f9d039a5c023a14d52b031e
7
- data.tar.gz: b227ee2a57df19679fff4767d23734ff4fff44cb92d98494ec1f75c97669793356a6b4610470de0885dba064d91a455ec93e8b0eeac092493ebe50331f67779c
6
+ metadata.gz: ddbc32e5e1dd43e8ca84e27e2a1bd02117dab786ab085900288990de9e32c7bfa406ffb23b3c32c7cb48a8c6da1c404f71f49b7064372b23bdfe922591de83a3
7
+ data.tar.gz: 2e4d091cfa1abcf667cf59dde4384f88c885825f436b7dd746528d9d5316f00ec3427db1cbb02176230bf9458d164d0dcaada35e1042ecf790dad3f83ba16a0c
@@ -7,17 +7,20 @@ class SystemSettings extends Lanes.Models.Base
7
7
  settings: "object"
8
8
 
9
9
  associations:
10
- logo: { model: "Lanes.Models.Asset" }
10
+ logo: { model: "Lanes.Models.Asset" }
11
+ smtp: { model: "Lanes.Models.SmtpSettings" }
12
+ print_logo: { model: "Lanes.Models.Asset" }
11
13
 
12
14
  modelTypeIdentifier: -> 'system-settings'
13
15
  url: -> Lanes.config.api_path + '/system-settings'
14
16
  initialize: ->
15
17
  @on('change:settings', @setDefaultSettings)
18
+ @smtp.set(@settings?.lanes?.smtp)
16
19
  @setDefaultSettings()
17
20
 
18
21
  setDefaultSettings: ->
19
22
  @settings ||= {}
20
- @settings.lanes || = {}
23
+ @settings.lanes ||= {}
21
24
 
22
25
  forExtension: (ext) ->
23
26
  @settings[ext] ||= {}
@@ -25,17 +28,27 @@ class SystemSettings extends Lanes.Models.Base
25
28
  setValueForExtension: (ext, key, value) ->
26
29
  @forExtension(ext)[key] = value
27
30
 
31
+ set: (data) ->
32
+ ret = super
33
+ @smtp.set(@settings?.lanes?.smtp)
34
+ ret
35
+
36
+ dataForSave: ->
37
+ data = super
38
+ data.settings.lanes.smtp = @smtp.serialize()
39
+ data
40
+
28
41
  class Config extends Lanes.Models.State
29
42
 
30
43
  session:
31
- csrf_token: { type: 'string', setOnce: true }
32
- root_path: { type: 'string', setOnce: true }
33
- api_path: { type: 'string', default: '/api' }
34
- api_host: { type: 'string', default: window.location.host }
35
- environment: { type: 'string', setOnce: true }
44
+ csrf_token: { type: 'string', setOnce: true }
45
+ root_path: { type: 'string', setOnce: true }
46
+ api_path: { type: 'string', default: '/api' }
47
+ environment: { type: 'string', setOnce: true }
36
48
  system_settings: { type: 'state', required: true }
37
49
  assets_path_prefix: { type: 'string', setOnce: true }
38
- initial_workspace_screen_id: { type: 'string', setOnce: true }
50
+ api_host: { type: 'string', default: "//#{window.location.host }" }
51
+ initial_workspace_screen_id: { type: 'string', setOnce: true }
39
52
 
40
53
  derived:
41
54
  env:
@@ -56,4 +69,8 @@ class Config extends Lanes.Models.State
56
69
  @set(options)
57
70
  Lanes.Extensions.setBootstrapData(options) if _.isObject(options)
58
71
 
59
- Lanes.config = new Config
72
+ configInstance = new Config
73
+
74
+ Object.defineProperty Lanes, 'config',
75
+ get: -> configInstance
76
+ set: -> throw new Error("Unable to reset config")
@@ -25,7 +25,7 @@ class Lanes.Access.Screens.UserManagement extends Lanes.React.Screen
25
25
  getSelection={@rolesForUser}
26
26
  setSelection={@setRolesForUser}
27
27
  choices={Lanes.Models.Role.all.models}
28
- fetchWhenOpen={false}
28
+ fetchOnSelect={false}
29
29
  name="role_names"
30
30
  />
31
31
 
@@ -14,15 +14,19 @@ Lanes.Components.Grid.EditingMixin = {
14
14
  React.PropTypes.bool, React.PropTypes.func
15
15
  ])
16
16
 
17
+ cleanProps: (props) ->
18
+ _.omit(props, 'index', 'field', 'props', 'query', 'rowIndex')
19
+
17
20
  editorTypes:
18
21
  text: (props) ->
19
- props.value ||= ''
20
- <input type="text" {...props}
22
+ inputProps = _.omit(@cleanProps(props), 'model')
23
+ inputProps.value ?= ''
24
+ <input type="text" {...inputProps}
21
25
  onChange={_.partial(@onFieldChange, _, props.field)} />
22
26
  bigdec: (props) ->
23
- <LC.NumberInput unstyled {...props} />
27
+ <LC.NumberInput unstyled {...@cleanProps(props)} />
24
28
  date: (props) ->
25
- <LC.DateTime {...props} inputOnly step={15}
29
+ <LC.DateTime {...@cleanProps(props)} inputOnly step={15}
26
30
  onChange={_.partial(@onDateFieldChange, _, props.field)} />
27
31
 
28
32
  displayTypes:
@@ -1,5 +1,9 @@
1
1
  ##= require ./EditingMixin
2
-
2
+ BAD_PROPS = [
3
+ 'position', 'model', 'index', 'syncImmediatly', 'query',
4
+ 'onCancel', 'onSave', 'cellStyles', 'editors', 'rowIndex',
5
+ 'rowHeight', 'allowDelete'
6
+ ]
3
7
  Lanes.Components.Grid.PopoverMixin = {
4
8
 
5
9
  mixins: [
@@ -25,6 +29,8 @@ Lanes.Components.Grid.PopoverMixin = {
25
29
  props.arrowOffsetTop = Math.min(position.top + 20, (props.height - 75))
26
30
  props.positionTop = Math.max(5, position.top - props.arrowOffsetTop + (position.rowHeight / 2))
27
31
 
32
+ props = _.omit(props, BAD_PROPS)
33
+
28
34
  <div className="editor po">
29
35
  <BS.Popover
30
36
  id="editing-form"
@@ -25,6 +25,12 @@ class Lanes.Components.Modal extends Lanes.React.Component
25
25
  getInitialState: ->
26
26
  show: false
27
27
 
28
+ setBusy: (isBusy) ->
29
+ @setState({isBusy})
30
+
31
+ busyMessage: ->
32
+ (if _.isString(@state.isBusy) then @state.isBusy else '') + '…'
33
+
28
34
  onOkButton: (ev) -> @state.onOk?(this, ev)
29
35
  onCancelButton: (ev) -> @state.onCancel?(this, ev)
30
36
  onButton: (ev, btn) ->
@@ -56,7 +62,9 @@ class Lanes.Components.Modal extends Lanes.React.Component
56
62
  button.eventKey ||= (button.key or button.title).toLowerCase()
57
63
  <BS.Button key={button.title}
58
64
  bsStyle={button.style || 'default'} className={name}
59
- onClick={_.partial(@onButton, _, button)}>{button.title}</BS.Button>
65
+ disabled={!!@state.isBusy}
66
+ onClick={_.partial(@onButton, _, button)}
67
+ >{button.title}</BS.Button>
60
68
 
61
69
  cls = _.classnames('lanes-modal', @state.className, @context.uistate?.layout_size)
62
70
  Body = @state.body
@@ -74,6 +82,8 @@ class Lanes.Components.Modal extends Lanes.React.Component
74
82
  </BS.Modal.Header>
75
83
 
76
84
  <BS.Modal.Body style={maxHeight: @context.viewport.height - 250}>
85
+ <LC.NetworkActivityOverlay visible={!!@state.isBusy}
86
+ message={@busyMessage()} />
77
87
  <Body {...@props} modal={@} />
78
88
  </BS.Modal.Body>
79
89
 
@@ -8,8 +8,13 @@ class Lanes.Components.RecordFinder extends Lanes.React.Component
8
8
  parentModel: Lanes.PropTypes.State
9
9
  commands: React.PropTypes.object
10
10
  onModelSet: React.PropTypes.func
11
+ autoFocus: React.PropTypes.bool
12
+ inputType: React.PropTypes.string
11
13
  associationName: React.PropTypes.string
12
14
 
15
+ getDefaultProps: ->
16
+ inputType: 'text'
17
+
13
18
  mixins: [
14
19
  Lanes.Components.Form.InputFieldMixin
15
20
  ]
@@ -63,15 +68,14 @@ class Lanes.Components.RecordFinder extends Lanes.React.Component
63
68
 
64
69
  renderInputField: (props, handlers) ->
65
70
  model = @props.parentModel or @props.model
66
-
67
71
  <BS.InputGroup className="record-finder">
68
- <BS.FormControl
69
- {...props} {...handlers}
72
+ <input className="form-control"
73
+ type={@props.inputType}
74
+ autoFocus={@props.autoFocus}
70
75
  onChange={@fieldMixinSetValue}
71
76
  value={@getValue()}
72
77
  onKeyPress={@onKeyPress}
73
78
  />
74
-
75
79
  <BS.InputGroup.Button>
76
80
  <button className='btn btn-primary' onClick={@showFinder}>
77
81
  <LC.Icon lg
@@ -16,20 +16,22 @@ class Lanes.Components.DateTime extends Lanes.React.Component
16
16
  handleKeyDown: (ev) ->
17
17
  @props.onEnter() if ev.key is 'Enter'
18
18
 
19
- handleDateTimeChange: (val) ->
20
- @fieldMixinSetValue({target: {value: val}})
21
-
22
-
23
19
  renderDisplay: (props) ->
24
20
  clean = LC.Form.FieldMixin.statics.cleanSizeProps(props)
25
21
  <BS.FormControl.Static {...clean}>
26
- {_.moment(@model[@props.name]).format(@props.format)}
22
+ {@getDateValue().format(this.props.format)}
27
23
  </BS.FormControl.Static>
28
24
 
25
+ getDateValue: ->
26
+ _.moment.utc(@fieldMixinGetValue())
27
+
28
+ handleDateTimeChange: (val) ->
29
+ @fieldMixinSetValue({target: {value: Lanes.u.utcToLocalDate(val)}})
30
+
29
31
  renderEdit: (props) ->
30
32
  props = _.extend({
31
33
  ref: 'control'
32
- value: @fieldMixinGetValue()
34
+ value: Lanes.u.dateToUTC(@getDateValue().toDate())
33
35
  onChange: @handleDateTimeChange
34
36
  }, @props)
35
37
  props = _.omit(LC.Form.FieldMixin.statics.cleanSizeProps(props), 'writable')
@@ -1,4 +1,4 @@
1
- Lanes.Components.Form || = {}
1
+ Lanes.Components.Form ||= {}
2
2
 
3
3
 
4
4
  Lanes.Components.Form.FieldMixin = {
@@ -152,9 +152,9 @@ Lanes.Components.Form.FieldMixin = {
152
152
  'has-error': hasError
153
153
  }
154
154
  )
155
-
155
+ fieldProps = Lanes.u.cleanBsSizes(props)
156
156
  field = (@[ "render#{method}" ] || @["_fieldMixinRender#{method}"])(
157
- if @props.fieldOnly then props else _.omit(props, 'className')
157
+ if @props.fieldOnly then fieldProps else _.omit(fieldProps, 'className')
158
158
  )
159
159
  if @props.fieldOnly
160
160
  field
@@ -34,7 +34,7 @@ class Lanes.Components.Icon extends Lanes.React.BaseComponent
34
34
  'clickable' : @props.clickable or (@props.tooltip and @props.tooltipProps.trigger is 'click')
35
35
 
36
36
  icon =
37
- <i style={@props.style} className={classes} />
37
+ <i style={@props.style} className={classes} onClick={@props.onClick} />
38
38
 
39
39
  if @props.tooltip
40
40
  props = _.extend({}, DEFAULT_TOOLTIP_PROPS, @props.tooltipProps)
@@ -2,6 +2,7 @@ class Lanes.Components.ImageAsset extends Lanes.React.Component
2
2
 
3
3
  propTypes:
4
4
  asset: Lanes.PropTypes.Model.isRequired
5
+ label: React.PropTypes.string
5
6
  size: React.PropTypes.oneOf([
6
7
  'thumb', 'medium', 'original'
7
8
  ]).isRequired
@@ -11,8 +12,9 @@ class Lanes.Components.ImageAsset extends Lanes.React.Component
11
12
 
12
13
  listenNetworkEvents: true
13
14
 
14
- bindEvents: ->
15
- model: "change:#{@props.name} change:#{@props.name}_data"
15
+ mixins: [
16
+ Lanes.React.Mixins.ReadEditingState
17
+ ]
16
18
 
17
19
  handleImageChange: (ev) ->
18
20
  ev.preventDefault()
@@ -24,8 +26,25 @@ class Lanes.Components.ImageAsset extends Lanes.React.Component
24
26
  blankImage: ->
25
27
  null
26
28
 
29
+ Label: ->
30
+ return null unless @props.label
31
+ <label>{@props.label}</label>
32
+
33
+ Edit: ->
34
+ return null unless @isEditingRecord()
35
+ <form>
36
+ <label className="selector">
37
+ <span>
38
+ {if @asset.isPresent then 'Change' else 'Add'}
39
+ </span>
40
+ <input id='file' className="file" type="file"
41
+ onChange={@handleImageChange} />
42
+ </label>
43
+ </form>
44
+
27
45
  render: ->
28
46
  Component = if @asset.hasImage then @renderImage else @blankImage
47
+
29
48
  className = _.classnames('image-asset', @props.className, {
30
49
  'with-image': @asset.hasImage
31
50
  })
@@ -33,14 +52,7 @@ class Lanes.Components.ImageAsset extends Lanes.React.Component
33
52
  {...Lanes.u.bsSizes(@props)}
34
53
  className={className}
35
54
  >
55
+ <@Label />
36
56
  <Component />
37
- <form>
38
- <label className="selector">
39
- <span>
40
- {if @asset.isPresent then 'Change' else 'Add'}
41
- </span>
42
- <input id='file' className="file" type="file"
43
- onChange={@handleImageChange} />
44
- </label>
45
- </form>
57
+ <@Edit />
46
58
  </BS.Col>
@@ -1,3 +1,5 @@
1
+ ##= require 'lanes/components/shared/Icon'
2
+
1
3
  class Lanes.Components.NetworkActivityOverlay extends Lanes.React.Component
2
4
 
3
5
  propTypes:
@@ -6,6 +6,8 @@ class BaseExtension
6
6
  title: ->
7
7
  _.titleize @identifier
8
8
 
9
+ setBootstrapData: (data) ->
10
+ @data = data
9
11
 
10
12
  Lanes.Extensions.Base = Lanes.lib.MakeBaseClass(
11
13
  Lanes.Vendor.Ampersand.State, BaseExtension
@@ -0,0 +1,30 @@
1
+ class Lanes.lib.AssetLoader
2
+
3
+ constructor: (urls, cb) ->
4
+ finished = 0
5
+ completed = {}
6
+ onComplete = (url, success, error = false) ->
7
+ finished += 1
8
+ completed[url] = { success: success == true, error: error }
9
+ cb(completed) if finished == urls.length
10
+
11
+ for baseUrl in urls
12
+ url = "#{baseUrl}?#{parseInt(Math.random() * 100000)}"
13
+ if /.css($|\?)/.test(url)
14
+ Lanes.lib.loader.css(url, onComplete)
15
+ else
16
+ Lanes.lib.loader.js(url, onComplete)
17
+
18
+ Lanes.lib.RequestAssets = (urls...) ->
19
+ urls = urls[0] if urls.length == 1 && _.isArray(urls[0])
20
+ new _.Promise( (resolve, reject) ->
21
+
22
+ new Lanes.lib.AssetLoader(urls, (completed) ->
23
+ failures = _.pick(completed, (status, url) -> !status.success )
24
+ if _.isEmpty(failures)
25
+ resolve(completed)
26
+ else
27
+ Lanes.warn( _.keys(failures).join(',') + " failed to load" )
28
+ reject( failures )
29
+ )
30
+ )
@@ -3,6 +3,7 @@
3
3
  //= require ./objToParam
4
4
  //= require ./ModuleSupport
5
5
  //= require ./loader
6
+ //= require ./RequestAssets
6
7
  //= require ./MakeBaseClass
7
8
  //= require ./el
8
9
  //= require ./polyfills
@@ -0,0 +1,93 @@
1
+ //= require ./namespace
2
+
3
+ // https://pie.gd/test/script-link-events/
4
+
5
+ (function( w ){
6
+ var insertBefore = function(){
7
+ var refs = doc.getElementsByTagName( "head" )[ 0 ].childNodes;
8
+ return refs[ refs.length - 1];
9
+ };
10
+
11
+ var doc = w.document;
12
+
13
+ // https://github.com/filamentgroup/loadJS/blob/master/loadJS.js
14
+ var loadJS = function( src, cb ){
15
+ "use strict";
16
+ var ref = insertBefore();
17
+ var script = doc.createElement( "script" );
18
+ script.src = src;
19
+ script.async = true;
20
+ ref.parentNode.insertBefore( script, ref );
21
+ if (cb && typeof(cb) === "function") {
22
+ script.onload = function(ev){
23
+ cb(script, ev);
24
+ }
25
+ }
26
+ return script;
27
+ };
28
+
29
+
30
+ // https://github.com/filamentgroup/loadCSS/blob/master/src/loadCSS.js
31
+ var loadCSS = function( href, cb){
32
+ var ss = doc.createElement( "link" );
33
+ var ref = insertBefore();
34
+
35
+ var sheets = doc.styleSheets;
36
+ ss.rel = "stylesheet";
37
+ ss.href = href;
38
+ ss.media = "only x";
39
+
40
+ // wait until body is defined before injecting link. This ensures a non-blocking load in IE11.
41
+ function ready( cb ){
42
+ if( doc.body ){
43
+ return cb();
44
+ }
45
+ setTimeout(function(){
46
+ ready( cb );
47
+ });
48
+ }
49
+ // Inject link
50
+ // Note: the ternary preserves the existing behavior of "before" argument, but we could choose to change the argument to "after" in a later release and standardize on ref.nextSibling for all refs
51
+ // Note: `insertBefore` is used instead of `appendChild`, for safety re: http://www.paulirish.com/2011/surefire-dom-element-insertion/
52
+ ready( function(){
53
+ ref.parentNode.insertBefore( ss, ref.nextSibling );
54
+ });
55
+ // A method (exposed on return object for external use) that mimics onload by polling document.styleSheets until it includes the new sheet.
56
+ var onloadcssdefined = function( cb ){
57
+ var resolvedHref = ss.href;
58
+ var i = sheets.length;
59
+ while( i-- ){
60
+ if( sheets[ i ].href === resolvedHref ){
61
+ return cb(sheets[i]);
62
+ }
63
+ }
64
+ setTimeout(function() {
65
+ onloadcssdefined( cb );
66
+ });
67
+ };
68
+
69
+ function loadCB(ev){
70
+ if( ss.addEventListener ){
71
+ ss.removeEventListener( "load", loadCB );
72
+ }
73
+ ss.media = "all";
74
+ if (cb && typeof(cb) === "function") {
75
+ cb(ss, ev);
76
+ }
77
+ }
78
+
79
+ // once loaded, set link's media back to `all` so that the stylesheet applies once it loads
80
+ if( ss.addEventListener ){
81
+ ss.addEventListener( "load", loadCB);
82
+ } else {
83
+ onloadcssdefined( loadCB );
84
+ }
85
+ return ss;
86
+ };
87
+
88
+ w.Lanes.lib.loader = {
89
+ js: loadJS,
90
+ css: loadCSS
91
+ };
92
+
93
+ }( typeof global !== "undefined" ? global : this ));