chr 0.1.5 → 0.2.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gruntfile.coffee +6 -3
  3. data/LICENSE.md +1 -1
  4. data/README.md +286 -7
  5. data/app/assets/javascripts/chr-dist.js +1031 -580
  6. data/app/assets/javascripts/chr.coffee +7 -4
  7. data/app/assets/javascripts/chr/core/chr.coffee +88 -37
  8. data/app/assets/javascripts/chr/core/item.coffee +57 -35
  9. data/app/assets/javascripts/chr/core/{list-scroll.coffee → list-pagination.coffee} +6 -3
  10. data/app/assets/javascripts/chr/core/list-reorder.coffee +3 -3
  11. data/app/assets/javascripts/chr/core/list-search.coffee +20 -11
  12. data/app/assets/javascripts/chr/core/list.coffee +163 -89
  13. data/app/assets/javascripts/chr/core/module.coffee +75 -35
  14. data/app/assets/javascripts/chr/core/view.coffee +117 -61
  15. data/app/assets/javascripts/chr/store/{store.coffee → _array-store.coffee} +53 -106
  16. data/app/assets/javascripts/chr/store/_object-store.coffee +28 -0
  17. data/app/assets/javascripts/chr/store/mongosteen-array-store.coffee +199 -0
  18. data/app/assets/javascripts/chr/store/mongosteen-object-store.coffee +52 -0
  19. data/app/assets/javascripts/chr/store/rest-array-store.coffee +142 -0
  20. data/app/assets/javascripts/chr/store/rest-object-store.coffee +79 -0
  21. data/app/assets/stylesheets/core/_list.scss +20 -25
  22. data/app/assets/stylesheets/core/_main.scss +3 -4
  23. data/app/assets/stylesheets/core/_mixins.scss +33 -2
  24. data/app/assets/stylesheets/core/_responsive.scss +30 -9
  25. data/app/assets/stylesheets/form/_input_checkbox.scss +18 -14
  26. data/bower.json +3 -2
  27. data/chr.gemspec +1 -1
  28. data/docs/assets.md +0 -0
  29. data/docs/basics.md +0 -0
  30. data/docs/bootstrap-data.md +0 -0
  31. data/docs/custom-inputs.md +0 -0
  32. data/docs/form.md +0 -0
  33. data/docs/internals.md +0 -0
  34. data/docs/nested-forms.md +0 -0
  35. data/docs/redactor-js.md +0 -0
  36. data/docs/scopes.md +0 -0
  37. data/lib/chr/version.rb +1 -1
  38. data/package.json +1 -1
  39. metadata +19 -7
  40. data/app/assets/javascripts/chr/store/store-mongosteen.coffee +0 -111
  41. data/app/assets/javascripts/chr/store/store-rest.coffee +0 -90
@@ -2,43 +2,38 @@
2
2
  header {
3
3
  .search {
4
4
  @include absolutePosition(0 0 inherit inherit);
5
- height: 40px; overflow: hidden; width: 40px;
5
+ width: 40px; height: 40px; overflow: hidden;
6
6
 
7
- .icon { @include absolutePosition(0 inherit inherit 0); z-index: 0; @extend .icon-search; }
8
- input { display: none; height: 42px; width: 100%; padding: 0 5em 0 2.5em; outline-style: none; border: none; }
9
- .cancel { display: none; @include absolutePosition(0 1em initial initial); z-index: 0; color: $positiveColor; }
7
+ .icon { @extend .icon-search; @include absolutePosition(0 inherit inherit 0); }
8
+ input { height: 40px; width: 100%; padding: 0 5em 0 2.5em; outline: none; border: none; }
9
+ input { display: none; }
10
+ .cancel { @include headerButton; @include absolutePosition(0 1em initial initial); }
11
+ .cancel { display: none; }
10
12
  }
11
13
  .new + .search { @include absolutePosition(0 40px inherit inherit); }
14
+
15
+ .spinner { @include spinner; position: absolute; margin: .5em 0 0 -2.25em; }
16
+ .spinner { display: none; }
12
17
  }
13
18
 
14
19
  &.list-search {
15
20
  header {
16
- .search { @include absolutePosition(0 0 inherit 0);
17
- width: 100%; z-index: 1; background-color: $white;
18
- input { display: block; }
19
- .cancel { display: inline; &:hover { opacity: .5; } }
20
- .icon {
21
- &:hover { cursor: pointer; opacity: 1; }
22
- &:before { border-color: $stableColor; }
23
- &:after { background-color: $stableColor; }
24
- }
21
+ .search {
22
+ @include absolutePosition(0 0 inherit 0);
23
+ width: 100%; background-color: $white;
24
+
25
+ input { display: block; }
26
+ .cancel { display: inline; }
27
+ .icon:hover { opacity: 1; }
28
+ .icon:before { border-color: $stableColor; }
29
+ .icon:after { background-color: $stableColor; }
25
30
  }
26
31
  .new + .search { @include absolutePosition(0 0 inherit 0); }
27
32
  }
28
33
  .item-folder { display: none; }
29
34
  }
30
35
 
31
- .items:after {
32
- content: 'Loading...';
33
- font-size: .8em; text-align: center; width: 100%; color: $stableColor; display: block; margin-top: 1.5em;
34
- opacity: 0; @include transition(opacity .25s);
35
- }
36
-
37
- &.list-loading .items:after {
38
- opacity: 1;
36
+ &.show-spinner {
37
+ header .spinner { display: inline-block; }
39
38
  }
40
39
  }
41
-
42
-
43
-
44
-
@@ -4,7 +4,7 @@ html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
4
4
  font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
5
5
  a { text-decoration: none; }
6
6
  }
7
- html, body, .view { overflow: hidden; } // .module
7
+ html, body, .view { overflow: hidden; }
8
8
 
9
9
  /* Menu -------------------------------------------------------------------- */
10
10
  .menu:before { content: 'CHR'; font-weight: 800; color: $contrastColor; line-height: 2.7;
@@ -15,11 +15,10 @@ html, body, .view { overflow: hidden; } // .module
15
15
  /* Headers ----------------------------------------------------------------- */
16
16
  .view header,
17
17
  .list header { text-align: center; position: relative; z-index: 1; line-height: 2.6; max-height: 42px; background-color: $white;
18
- .title { font-weight: 500; padding: 1px 60px 0 40px; color: $black;
19
- @include truncate; }
18
+ .title { font-weight: 500; color: $black; display: inline-block; width: 70%; @include truncate; }
20
19
  .back, .close { @include absolutePosition(0 inherit inherit 0); @extend .icon-back; overflow: hidden; height: 41px; }
21
20
  .new { @include absolutePosition(0 0 inherit inherit); @extend .icon-plus; }
22
- .save { @include absolutePosition(0 1em inherit inherit); color: $positiveColor; &:hover { opacity: .5; } }
21
+ .save { @include absolutePosition(0 1em inherit inherit); @include headerButton; }
23
22
  }
24
23
 
25
24
  /* Items ------------------------------------------------------------------- */
@@ -10,15 +10,46 @@
10
10
  }
11
11
 
12
12
  @mixin border($color) {
13
- &:after { content: ''; display: block; height: 1px; //width: 100%;
13
+ &:after { content: ''; display: block; height: 1px;
14
14
  background-color: $color; @include position(absolute, 0px 0px null 1em); }
15
15
  }
16
16
 
17
17
  @mixin noBorder { &:after { display: none; } }
18
18
 
19
+ @mixin noFocus { &:focus { outline: none; } }
20
+
19
21
  @mixin customScrollbar {
20
22
  &::-webkit-scrollbar { width: 6px; background-color: $neutralColor; }
21
23
  &::-webkit-scrollbar-thumb { background-color: $contrastColor; border-radius: 3px; }
22
24
  }
23
25
 
24
- @mixin scrollable { overflow: hidden; overflow-y: scroll; -webkit-overflow-scrolling: touch; }
26
+ @mixin scrollable { overflow: hidden; overflow-y: scroll; -webkit-overflow-scrolling: touch; }
27
+
28
+ @mixin spinner {
29
+ border: .25em solid rgba($positiveColor, 0.2);
30
+ border-left: .25em solid $positiveColor;
31
+ -webkit-animation: spinning 1.1s infinite linear; animation: spinning 1.1s infinite linear;
32
+ &, &:after { border-radius: 50%; width: 1.75em; height: 1.75em; }
33
+ }
34
+
35
+ @-webkit-keyframes spinning {
36
+ 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }
37
+ 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); }
38
+ }
39
+
40
+ @keyframes spinning {
41
+ 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }
42
+ 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); }
43
+ }
44
+
45
+ @mixin headerButton($color: $positiveColor) {
46
+ color: $color; &:hover { opacity: .5; }
47
+ }
48
+
49
+ @mixin shadow {
50
+ box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
51
+ }
52
+
53
+
54
+
55
+
@@ -2,38 +2,59 @@
2
2
  $tablet: "screen and (min-width:768px)";
3
3
  $desktop: "screen and (min-width:1150px)";
4
4
 
5
+
5
6
  /* Mobile Layout */
6
7
  .sidebar { @include absolutePosition(0 0 0 0); z-index: 1; }
7
8
  .module { @include absolutePosition(0 0 0 0); z-index: 2; }
8
9
  .view { @include absolutePosition(0 0 0 0); z-index: 3; background-color: #fff; }
9
10
  .list { @include absolutePosition(0 0 0 0); z-index: 0; overflow: hidden; background-color: #fff; }
10
11
 
12
+
11
13
  /* Tablet Layout */
12
14
  @media #{$tablet} {
13
15
  .sidebar { right: inherit; width: 9em; }
14
16
  .module { right: inherit; left: 9em; width: 20em; }
15
- .view { left: 29em; }
16
- .list { font-size: .9em; }
17
- .items .item:active { background: $neutralColor; }
17
+ .view { left: 29em; &.fullsize { left: 9em; } }
18
+ .list header,
19
+ .list .items { font-size: .9em; }
20
+ .list header { line-height: 2.9em; }
18
21
  .module .list:first-child .back { display: none; }
19
- .view header .close { @include absolutePosition(0 inherit inherit 1em); color: $positiveColor; &:before { display: none; } }
20
- .view header .title { padding-left: 64px; }
21
- .module, .view { box-shadow: 0 0 2px rgba(0, 0, 0, 0.2); }
22
+ .view header .close { @include absolutePosition(0 inherit inherit 1em); @include headerButton; width: auto; &:before { display: none; } }
23
+ .module, .view { @include shadow; }
22
24
  .module {
23
25
  &:after {
24
26
  display: block; content: ''; width: 4px; @include position(absolute, 0px -3px 0px null);
25
27
  background-color: $white; border-left: 1px solid $neutralColor;
26
28
  }
27
29
  }
28
- // custom scrollbar
29
- .redactor-editor, textarea.redactor, .view .input-stacked textarea, .view > form, .list .items { @include customScrollbar(); }
30
+
31
+ // scrollbars
32
+ .view .input-stacked textarea, .view > form, .list .items { @include customScrollbar(); }
33
+
34
+ // layout when first list always shown
35
+ .module.first-list-aside { width: auto; right: 0;
36
+ .list {
37
+ &:first-child { width: 20em; }
38
+ &:not(:first-child) { left: 20em; }
39
+ &:first-child .items { overflow-y: hidden; }
40
+ &:first-child .icon-folder { display: none; }
41
+ &:not(:first-child) { @include shadow; }
42
+ &:not(:first-child) header .back { display: none; }
43
+ }
44
+ }
30
45
  }
31
46
 
47
+
32
48
  /* Desktop Layout */
33
49
  @media #{$desktop} {
34
50
  .sidebar { width: 10em; }
35
51
  .module { left: 10em; width: 22em; }
36
- .view { left: 32em; }
52
+ .view { left: 32em; &.fullsize { left: 10em; } }
53
+
54
+ .module.first-list-aside {
55
+ .list:first-child { width: 22em; }
56
+ .list:not(:first-child) { left: 22em; }
57
+ }
37
58
  }
38
59
 
39
60
 
@@ -1,17 +1,4 @@
1
- /* Checkbox ---------------------------------------------------------------- */
2
- .view .input-checkbox {
3
- padding: .8em 1em 1em;
4
-
5
- input { display: inline; width: auto; margin-right: .5em; }
6
- .label { display: inline; }
7
- }
8
-
9
- /* Switch ------------------------------------------------------------------ */
10
- .view .input-switch { padding-top: .75em; }
11
- .view .input-switch .switch {
12
- float: right;
13
- margin-top: -1.8em;
14
-
1
+ @mixin switchControl() {
15
2
  $switch-width: 52px;
16
3
  $switch-padding: 2px;
17
4
  $switch-height: 32px;
@@ -84,4 +71,21 @@
84
71
  }
85
72
  }
86
73
  }
74
+ }
75
+
76
+ /* Checkbox ---------------------------------------------------------------- */
77
+ .view .input-checkbox {
78
+ padding: .8em 1em 1em;
79
+
80
+ input { display: inline; width: auto; margin-right: .5em; }
81
+ .label { display: inline; }
82
+ }
83
+
84
+ /* Switch ------------------------------------------------------------------ */
85
+ .view .input-switch { padding-top: .75em; }
86
+ .view .input-switch .switch {
87
+ float: right;
88
+ margin-top: -1.8em;
89
+
90
+ @include switchControl();
87
91
  }
data/bower.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "homepage": "https://github.com/slate-studio/chr",
5
5
  "authors": [
6
6
  "Slate Studio (http://www.slatestudio.com)"
7
7
  ],
8
8
  "license": "MIT",
9
- "description": "A simple and lightweight library for building data management web apps",
9
+ "description": "Powerful responsive javascript CMS for apps.",
10
10
  "main": "app/assets/stylesheets/_chr.scss, app/assets/javascripts/chr-dist.js",
11
11
  "keywords": [
12
12
  "library",
@@ -18,6 +18,7 @@
18
18
  "ignore": [
19
19
  "**/.*",
20
20
  "lib",
21
+ "docs",
21
22
  "chr.gemspec",
22
23
  "Gemfile",
23
24
  "Gemfile.lock",
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.email = 'alex@slatestudio.com'
11
11
  s.license = 'MIT'
12
12
  s.homepage = 'http://slatestudio.com'
13
- s.summary = 'A simple and lightweight library for building data management web apps'
13
+ s.summary = 'Powerful responsive javascript CMS for apps'
14
14
  s.description = <<-DESC
15
15
  Character is a library written in CoffeeScript with a help of jQuery that allows to
16
16
  build data management web applications in a fast and flexible way, e.g. CMS, news reader,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,3 +1,3 @@
1
1
  module Chr
2
- VERSION = "0.1.5"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "devDependencies": {
5
5
  "grunt": "^0.4.5",
6
6
  "grunt-contrib-clean": "^0.6.0",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Kravets
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-16 00:00:00.000000000 Z
11
+ date: 2015-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bourbon
@@ -72,8 +72,8 @@ files:
72
72
  - app/assets/javascripts/chr.coffee
73
73
  - app/assets/javascripts/chr/core/chr.coffee
74
74
  - app/assets/javascripts/chr/core/item.coffee
75
+ - app/assets/javascripts/chr/core/list-pagination.coffee
75
76
  - app/assets/javascripts/chr/core/list-reorder.coffee
76
- - app/assets/javascripts/chr/core/list-scroll.coffee
77
77
  - app/assets/javascripts/chr/core/list-search.coffee
78
78
  - app/assets/javascripts/chr/core/list.coffee
79
79
  - app/assets/javascripts/chr/core/module.coffee
@@ -89,9 +89,12 @@ files:
89
89
  - app/assets/javascripts/chr/form/input-string.coffee
90
90
  - app/assets/javascripts/chr/form/input-text.coffee
91
91
  - app/assets/javascripts/chr/form/nested-form.coffee
92
- - app/assets/javascripts/chr/store/store-mongosteen.coffee
93
- - app/assets/javascripts/chr/store/store-rest.coffee
94
- - app/assets/javascripts/chr/store/store.coffee
92
+ - app/assets/javascripts/chr/store/_array-store.coffee
93
+ - app/assets/javascripts/chr/store/_object-store.coffee
94
+ - app/assets/javascripts/chr/store/mongosteen-array-store.coffee
95
+ - app/assets/javascripts/chr/store/mongosteen-object-store.coffee
96
+ - app/assets/javascripts/chr/store/rest-array-store.coffee
97
+ - app/assets/javascripts/chr/store/rest-object-store.coffee
95
98
  - app/assets/javascripts/chr/vendor/jquery.scrollparent.js
96
99
  - app/assets/javascripts/chr/vendor/jquery.textarea_autosize.js
97
100
  - app/assets/javascripts/chr/vendor/jquery.typeahead.js
@@ -112,6 +115,15 @@ files:
112
115
  - app/assets/stylesheets/form/_nested_form.scss
113
116
  - bower.json
114
117
  - chr.gemspec
118
+ - docs/assets.md
119
+ - docs/basics.md
120
+ - docs/bootstrap-data.md
121
+ - docs/custom-inputs.md
122
+ - docs/form.md
123
+ - docs/internals.md
124
+ - docs/nested-forms.md
125
+ - docs/redactor-js.md
126
+ - docs/scopes.md
115
127
  - lib/chr.rb
116
128
  - lib/chr/engine.rb
117
129
  - lib/chr/version.rb
@@ -139,5 +151,5 @@ rubyforge_project: chr
139
151
  rubygems_version: 2.4.5
140
152
  signing_key:
141
153
  specification_version: 4
142
- summary: A simple and lightweight library for building data management web apps
154
+ summary: Powerful responsive javascript CMS for apps
143
155
  test_files: []
@@ -1,111 +0,0 @@
1
- # -----------------------------------------------------------------------------
2
- # Author: Alexander Kravets <alex@slatestudio.com>,
3
- # Slate Studio (http://www.slatestudio.com)
4
- #
5
- # Coding Guide:
6
- # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
- # -----------------------------------------------------------------------------
8
-
9
- # -----------------------------------------------------------------------------
10
- # MONGOSTEEN (RAILS) ARRAY/COLLECTION STORE IMPLEMENTATION
11
- # -----------------------------------------------------------------------------
12
- class @MongosteenArrayStore extends RestArrayStore
13
- # initial store configuration
14
- _initialize_database: ->
15
- @dataFetchLock = false
16
- @ajaxConfig =
17
- processData: false
18
- contentType: false
19
-
20
- @searchable = @config.searchable ? false
21
- @searchQuery = ''
22
-
23
- @pagination = @config.pagination ? true
24
- @pagesCounter = 0
25
-
26
- # disable pagination when bootstraped data provided
27
- if @config.data
28
- @pagination = false
29
-
30
-
31
- # generate resource api url
32
- _resource_url: (type, id) ->
33
- objectPath = if id then "/#{ id }" else ''
34
- url = "#{ @config.path }#{ objectPath }.json"
35
-
36
- if @config.urlParams
37
- extraParamsString = $.param(@config.urlParams)
38
- url = "#{ url }?#{ extraParamsString }"
39
-
40
- return url
41
-
42
-
43
- # get form data object from serialized form object,
44
- # it uses special format for object names for support of:
45
- # files, lists, nested objects
46
- _parse_form_object: (serializedFormObject) ->
47
- formDataObject = new FormData()
48
-
49
- for attr_name, attr_value of serializedFormObject
50
-
51
- # special case for LIST inputs, values separated with comma
52
- if attr_name.indexOf('[__LIST__') > -1
53
- attr_name = attr_name.replace('__LIST__', '')
54
- values = attr_value.split(',')
55
-
56
- for value in values
57
- formDataObject.append("#{ @config.resource }#{ attr_name }[]", value)
58
-
59
- else
60
- # special case for FILE inputs
61
- if attr_name.startsWith('__FILE__')
62
- attr_name = attr_name.replace('__FILE__', '')
63
-
64
- formDataObject.append("#{ @config.resource }#{ attr_name }", attr_value)
65
-
66
- return formDataObject
67
-
68
-
69
- # load next page objects from database, when finished
70
- # trigger 'objects_added' event
71
- load: (success) ->
72
- params = {}
73
-
74
- if @pagination
75
- params.page = @pagesCounter + 1
76
- params.perPage = _itemsPerPageRequest ? 20
77
-
78
- if @searchable && @searchQuery.length > 0
79
- params.search = @searchQuery
80
-
81
- params = $.param(params)
82
-
83
- @_ajax 'GET', null, params, ((dataObject) =>
84
- if dataObject.length > 0
85
- @pagesCounter = @pagesCounter + 1
86
-
87
- for o in dataObject
88
- @_add_data_object(o)
89
-
90
- success?()
91
- $(this).trigger('objects_added')
92
- ) #, callbacks.onError
93
-
94
-
95
- # load results for search query
96
- search: (@searchQuery, callback) ->
97
- @pagesCounter = 0
98
- @_reset_data()
99
- @load(callback)
100
-
101
-
102
- # reset data and load first page
103
- reset: (callback) ->
104
- @searchQuery = ''
105
- @pagesCounter = 0
106
- @_reset_data()
107
- @load(callback)
108
-
109
-
110
-
111
-