decidim-decidim_awesome 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +307 -0
  4. data/Rakefile +51 -0
  5. data/app/assets/config/decidim_admin_decidim_awesome_manifest.css +3 -0
  6. data/app/assets/config/decidim_admin_decidim_awesome_manifest.js +1 -0
  7. data/app/assets/config/decidim_decidim_awesome_manifest.css +5 -0
  8. data/app/assets/config/decidim_decidim_awesome_manifest.js +2 -0
  9. data/app/assets/images/decidim/decidim_awesome/loading.gif +0 -0
  10. data/app/assets/images/decidim/decidim_awesome/platoniq-logo.png +0 -0
  11. data/app/assets/javascripts/decidim/decidim_awesome/admin.js +2 -0
  12. data/app/assets/javascripts/decidim/decidim_awesome/admin/constraints.js.es6 +54 -0
  13. data/app/assets/javascripts/decidim/decidim_awesome/application.js +4 -0
  14. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/api_fetcher.js.es6 +38 -0
  15. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/categories.js.es6 +25 -0
  16. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/map.js.es6 +215 -0
  17. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/meetings.js.es6 +129 -0
  18. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/proposals.js.es6 +78 -0
  19. data/app/assets/javascripts/decidim/decidim_awesome/editors/markdown_view.js.es6 +12 -0
  20. data/app/assets/javascripts/decidim/decidim_awesome/editors/quill_editor.js.es6 +162 -0
  21. data/app/assets/javascripts/decidim/decidim_awesome/forms/autosave.js.es6 +90 -0
  22. data/app/assets/javascripts/decidim/decidim_awesome/proposals/images.js.es6 +25 -0
  23. data/app/assets/stylesheets/decidim/decidim_awesome/admin.scss +45 -0
  24. data/app/assets/stylesheets/decidim/decidim_awesome/admin/constraints.scss +37 -0
  25. data/app/assets/stylesheets/decidim/decidim_awesome/application.scss +8 -0
  26. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_iframe/iframe.scss +10 -0
  27. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/leaflet.scss.erb +9 -0
  28. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/map.scss +66 -0
  29. data/app/assets/stylesheets/decidim/decidim_awesome/editors/markdown_editor.scss +17 -0
  30. data/app/assets/stylesheets/decidim/decidim_awesome/editors/markdown_view.scss +27 -0
  31. data/app/assets/stylesheets/decidim/decidim_awesome/editors/quill_editor.scss +7 -0
  32. data/app/assets/stylesheets/decidim/decidim_awesome/forms/autosave.scss +17 -0
  33. data/app/awesome_overrides/presenters/decidim/proposals/proposal_presenter_override.rb +31 -0
  34. data/app/commands/decidim/decidim_awesome/admin/create_constraint.rb +47 -0
  35. data/app/commands/decidim/decidim_awesome/admin/destroy_constraint.rb +31 -0
  36. data/app/commands/decidim/decidim_awesome/admin/update_config.rb +44 -0
  37. data/app/commands/decidim/decidim_awesome/admin/update_constraint.rb +44 -0
  38. data/app/commands/decidim/decidim_awesome/create_editor_image.rb +34 -0
  39. data/app/controllers/concerns/decidim/decidim_awesome/needs_awesome_config.rb +17 -0
  40. data/app/controllers/decidim/decidim_awesome/admin/application_controller.rb +21 -0
  41. data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +37 -0
  42. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +44 -0
  43. data/app/controllers/decidim/decidim_awesome/admin/constraints_controller.rb +126 -0
  44. data/app/controllers/decidim/decidim_awesome/application_controller.rb +14 -0
  45. data/app/controllers/decidim/decidim_awesome/editor_images_controller.rb +50 -0
  46. data/app/controllers/decidim/decidim_awesome/iframe_component/application_controller.rb +15 -0
  47. data/app/controllers/decidim/decidim_awesome/iframe_component/iframe_controller.rb +33 -0
  48. data/app/controllers/decidim/decidim_awesome/map_component/application_controller.rb +15 -0
  49. data/app/controllers/decidim/decidim_awesome/map_component/map_controller.rb +31 -0
  50. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +22 -0
  51. data/app/forms/decidim/decidim_awesome/admin/constraint_form.rb +20 -0
  52. data/app/forms/decidim/decidim_awesome/admin/intergram_form.rb +21 -0
  53. data/app/forms/decidim/decidim_awesome/editor_image_form.rb +16 -0
  54. data/app/helpers/decidim/decidim_awesome/admin/config_constraints_helpers.rb +90 -0
  55. data/app/helpers/decidim/decidim_awesome/application_helper.rb +10 -0
  56. data/app/helpers/decidim/decidim_awesome/map_helper.rb +121 -0
  57. data/app/models/decidim/decidim_awesome/application_record.rb +10 -0
  58. data/app/models/decidim/decidim_awesome/awesome_config.rb +23 -0
  59. data/app/models/decidim/decidim_awesome/config_constraint.rb +13 -0
  60. data/app/models/decidim/decidim_awesome/editor_image.rb +24 -0
  61. data/app/permissions/decidim/decidim_awesome/permissions.rb +29 -0
  62. data/app/uploaders/decidim/decidim_awesome/image_uploader.rb +22 -0
  63. data/app/views/decidim/decidim_awesome/admin/checks/index.html.erb +35 -0
  64. data/app/views/decidim/decidim_awesome/admin/config/_constraints.html.erb +27 -0
  65. data/app/views/decidim/decidim_awesome/admin/config/_form_editors.html.erb +20 -0
  66. data/app/views/decidim/decidim_awesome/admin/config/_form_livechat.html.erb +44 -0
  67. data/app/views/decidim/decidim_awesome/admin/config/_form_proposals.html.erb +12 -0
  68. data/app/views/decidim/decidim_awesome/admin/config/_form_surveys.html.erb +9 -0
  69. data/app/views/decidim/decidim_awesome/admin/config/_modal.html.erb +11 -0
  70. data/app/views/decidim/decidim_awesome/admin/config/show.html.erb +15 -0
  71. data/app/views/decidim/decidim_awesome/admin/constraints/_form.html.erb +56 -0
  72. data/app/views/decidim/decidim_awesome/admin/constraints/new.html.erb +14 -0
  73. data/app/views/decidim/decidim_awesome/admin/constraints/show.html.erb +14 -0
  74. data/app/views/decidim/decidim_awesome/iframe_component/iframe/show.html.erb +9 -0
  75. data/app/views/decidim/decidim_awesome/map_component/map/error.erb +7 -0
  76. data/app/views/decidim/decidim_awesome/map_component/map/show.html.erb +74 -0
  77. data/app/views/layouts/decidim/_head.html.erb +5 -0
  78. data/app/views/layouts/decidim/admin/_header.html.erb +5 -0
  79. data/app/views/layouts/decidim/admin/decidim_awesome.html.erb +47 -0
  80. data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +20 -0
  81. data/app/views/layouts/decidim/decidim_awesome/_intergram_widget.html.erb +16 -0
  82. data/app/views/v0.21/layouts/decidim/_head.html.erb +34 -0
  83. data/app/views/v0.21/layouts/decidim/admin/_header.html.erb +9 -0
  84. data/app/views/v0.22/layouts/decidim/_head.html.erb +36 -0
  85. data/app/views/v0.22/layouts/decidim/admin/_header.html.erb +11 -0
  86. data/config/i18n-tasks.yml +10 -0
  87. data/config/locales/ca.yml +125 -0
  88. data/config/locales/cs.yml +125 -0
  89. data/config/locales/en.yml +176 -0
  90. data/config/locales/es.yml +125 -0
  91. data/config/locales/fr.yml +125 -0
  92. data/config/locales/sv.yml +125 -0
  93. data/db/migrate/20200324170000_create_decidim_awesome_config.rb +16 -0
  94. data/db/migrate/20200324230936_create_awesome_editor_images.rb +14 -0
  95. data/db/migrate/20200403142257_create_decidim_awesome_config_constraints.rb +13 -0
  96. data/db/seeds.rb +27 -0
  97. data/lib/decidim/decidim_awesome.rb +110 -0
  98. data/lib/decidim/decidim_awesome/admin.rb +10 -0
  99. data/lib/decidim/decidim_awesome/admin_engine.rb +45 -0
  100. data/lib/decidim/decidim_awesome/awesome_helpers.rb +55 -0
  101. data/lib/decidim/decidim_awesome/checksums.yml +15 -0
  102. data/lib/decidim/decidim_awesome/config.rb +129 -0
  103. data/lib/decidim/decidim_awesome/content_renderers.rb +9 -0
  104. data/lib/decidim/decidim_awesome/content_renderers/markdown_renderer.rb +18 -0
  105. data/lib/decidim/decidim_awesome/context_analyzers.rb +11 -0
  106. data/lib/decidim/decidim_awesome/context_analyzers/component_analyzer.rb +38 -0
  107. data/lib/decidim/decidim_awesome/context_analyzers/participatory_space_analyzer.rb +31 -0
  108. data/lib/decidim/decidim_awesome/context_analyzers/request_analyzer.rb +97 -0
  109. data/lib/decidim/decidim_awesome/engine.rb +38 -0
  110. data/lib/decidim/decidim_awesome/iframe_component/component.rb +59 -0
  111. data/lib/decidim/decidim_awesome/iframe_component/engine.rb +23 -0
  112. data/lib/decidim/decidim_awesome/map_component/component.rb +74 -0
  113. data/lib/decidim/decidim_awesome/map_component/engine.rb +23 -0
  114. data/lib/decidim/decidim_awesome/system_checker.rb +63 -0
  115. data/lib/decidim/decidim_awesome/test/factories.rb +36 -0
  116. data/lib/decidim/decidim_awesome/test/shared_examples/config_examples.rb +25 -0
  117. data/lib/decidim/decidim_awesome/test/themes/css.lvh.me.css +3 -0
  118. data/lib/decidim/decidim_awesome/test/themes/erb.lvh.me.scss.erb +2 -0
  119. data/lib/decidim/decidim_awesome/test/themes/scss.lvh.me.scss +1 -0
  120. data/lib/decidim/decidim_awesome/test/themes/test-theme/body.scss +4 -0
  121. data/lib/decidim/decidim_awesome/version.rb +10 -0
  122. data/vendor/assets/images/layers-2x.png +0 -0
  123. data/vendor/assets/images/layers.png +0 -0
  124. data/vendor/assets/images/marker-icon.png +0 -0
  125. data/vendor/assets/javascripts/codemirror-4.inline-attachment.js +89 -0
  126. data/vendor/assets/javascripts/form-storage.js +824 -0
  127. data/vendor/assets/javascripts/highlight.min.js +44 -0
  128. data/vendor/assets/javascripts/image-resize.min.js +1 -0
  129. data/vendor/assets/javascripts/image-upload.min.js +6 -0
  130. data/vendor/assets/javascripts/inline-attachment.js +399 -0
  131. data/vendor/assets/javascripts/inscrybmde.min.js +7 -0
  132. data/vendor/assets/javascripts/jquery.inline-attachment.js +66 -0
  133. data/vendor/assets/javascripts/leaflet.featuregroup.subgroup.js +6 -0
  134. data/vendor/assets/stylesheets/default.min.css +1 -0
  135. data/vendor/assets/stylesheets/foundation.min.css +1 -0
  136. data/vendor/assets/stylesheets/github.min.css +2 -0
  137. data/vendor/assets/stylesheets/inscrybmde.min.css +8 -0
  138. metadata +267 -0
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/core/test/factories"
4
+ require "decidim/proposals/test/factories"
5
+
6
+ FactoryBot.define do
7
+ factory :awesome_config, class: "Decidim::DecidimAwesome::AwesomeConfig" do
8
+ var { Faker::Hacker.noun }
9
+ value { Decidim::DecidimAwesome.config.to_a.sample(1).to_h }
10
+ organization { create :organization }
11
+ end
12
+
13
+ factory :config_constraint, class: "Decidim::DecidimAwesome::ConfigConstraint" do
14
+ settings { { Faker::Hacker.noun => Faker::Hacker.noun } }
15
+ awesome_config { create :awesome_config }
16
+ end
17
+
18
+ factory :editor_image, class: "Decidim::DecidimAwesome::EditorImage" do
19
+ image { Faker::Hacker.noun }
20
+ path { Faker::Internet.url(host: "", scheme: "") }
21
+ author { create :user }
22
+ organization { create :organization }
23
+ end
24
+
25
+ factory :map_component, parent: :component do
26
+ name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :proposals).i18n_name }
27
+ manifest_name { :awesome_map }
28
+ participatory_space { create(:participatory_process, :with_steps, organization: organization) }
29
+ end
30
+
31
+ factory :iframe_component, parent: :component do
32
+ name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :proposals).i18n_name }
33
+ manifest_name { :awesome_iframe }
34
+ participatory_space { create(:participatory_process, :with_steps, organization: organization) }
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples "javascript config vars" do
4
+ it "has DecidimAwesome object" do
5
+ expect(page.body).to have_content("window.DecidimAwesome")
6
+ expect(page.body).to have_content("window.DecidimAwesome.editor_uploader_path")
7
+ expect(page.body).to have_content("window.DecidimAwesome.texts")
8
+ end
9
+ end
10
+
11
+ shared_examples "has menu link" do |item|
12
+ it "shows the feature link" do
13
+ within ".secondary-nav" do
14
+ expect(page).to have_link(href: "/admin/decidim_awesome/config/#{item}")
15
+ end
16
+ end
17
+ end
18
+
19
+ shared_examples "do not have menu link" do |item|
20
+ it "do not show the feature link" do
21
+ within ".secondary-nav" do
22
+ expect(page).not_to have_link(href: "/admin/decidim_awesome/config/#{item}")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ body {
2
+ background: rgb(1, 2, 3);
3
+ }
@@ -0,0 +1,2 @@
1
+ /* Decidim <%= Decidim.version %> */
2
+ @import "test-theme/body.scss"
@@ -0,0 +1 @@
1
+ @import "test-theme/body.scss"
@@ -0,0 +1,4 @@
1
+ body{
2
+ background: darken(#f00, 10%);
3
+ background: rgb(1, 2, 3);
4
+ }
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This holds the decidim-decidim_awesome version.
5
+ module DecidimAwesome
6
+ VERSION = "0.5.1"
7
+ COMPAT_DECIDIM_VERSION = [">= 0.21.0", "< 0.23"].freeze
8
+ DECIDIM_VERSION = "0.22"
9
+ end
10
+ end
@@ -0,0 +1,89 @@
1
+ /*jslint newcap: true */
2
+ /*global inlineAttachment: false */
3
+ /**
4
+ * CodeMirror version for inlineAttachment
5
+ *
6
+ * Call inlineAttachment.attach(editor) to attach to a codemirror instance
7
+ */
8
+ (function() {
9
+ 'use strict';
10
+
11
+ var codeMirrorEditor = function(instance) {
12
+
13
+ if (!instance.getWrapperElement) {
14
+ throw "Invalid CodeMirror object given";
15
+ }
16
+
17
+ this.codeMirror = instance;
18
+ };
19
+
20
+ codeMirrorEditor.prototype.getValue = function() {
21
+ return this.codeMirror.getValue();
22
+ };
23
+
24
+ codeMirrorEditor.prototype.insertValue = function(val) {
25
+ this.codeMirror.replaceSelection(val);
26
+ };
27
+
28
+ codeMirrorEditor.prototype.setValue = function(val) {
29
+ var cursor = this.codeMirror.getCursor();
30
+ this.codeMirror.setValue(val);
31
+ this.codeMirror.setCursor(cursor);
32
+ };
33
+
34
+ /**
35
+ * Attach InlineAttachment to CodeMirror
36
+ *
37
+ * @param {CodeMirror} codeMirror
38
+ */
39
+ codeMirrorEditor.attach = function(codeMirror, options) {
40
+
41
+ options = options || {};
42
+
43
+ var editor = new codeMirrorEditor(codeMirror),
44
+ inlineattach = new inlineAttachment(options, editor),
45
+ el = codeMirror.getWrapperElement();
46
+
47
+ el.addEventListener('paste', function(e) {
48
+ inlineattach.onPaste(e);
49
+ }, false);
50
+
51
+ codeMirror.setOption('onDragEvent', function(data, e) {
52
+ if (e.type === "drop") {
53
+ e.stopPropagation();
54
+ e.preventDefault();
55
+ return inlineattach.onDrop(e);
56
+ }
57
+ });
58
+ };
59
+
60
+ var codeMirrorEditor4 = function(instance) {
61
+ codeMirrorEditor.call(this, instance);
62
+ };
63
+
64
+ codeMirrorEditor4.attach = function(codeMirror, options) {
65
+
66
+ options = options || {};
67
+
68
+ var editor = new codeMirrorEditor(codeMirror),
69
+ inlineattach = new inlineAttachment(options, editor),
70
+ el = codeMirror.getWrapperElement();
71
+
72
+ el.addEventListener('paste', function(e) {
73
+ inlineattach.onPaste(e);
74
+ }, false);
75
+
76
+ codeMirror.on('drop', function(data, e) {
77
+ if (inlineattach.onDrop(e)) {
78
+ e.stopPropagation();
79
+ e.preventDefault();
80
+ return true;
81
+ } else {
82
+ return false;
83
+ }
84
+ });
85
+ };
86
+
87
+ inlineAttachment.editors.codemirror4 = codeMirrorEditor4;
88
+
89
+ })();
@@ -0,0 +1,824 @@
1
+ /**
2
+ * Modules in this bundle
3
+ * @license
4
+ *
5
+ * form-storage:
6
+ * license: MIT (http://opensource.org/licenses/MIT)
7
+ * author: appleple
8
+ * version: 1.3.0
9
+ *
10
+ * decode-uri-component:
11
+ * license: MIT (http://opensource.org/licenses/MIT)
12
+ * author: Sam Verschueren <sam.verschueren@gmail.com>
13
+ * homepage: https://github.com/SamVerschueren/decode-uri-component#readme
14
+ * version: 0.2.0
15
+ *
16
+ * form-serialize:
17
+ * license: MIT (http://opensource.org/licenses/MIT)
18
+ * author: Roman Shtylman <shtylman@gmail.com>
19
+ * homepage: https://github.com/shtylman/form-serialize#readme
20
+ * version: 0.7.2
21
+ *
22
+ * query-string-es5:
23
+ * license: MIT (http://opensource.org/licenses/MIT)
24
+ * author: Sindre Sorhus <sindresorhus@gmail.com>
25
+ * homepage: https://github.com/sindresorhus/query-string#readme
26
+ * version: 6.1.4
27
+ *
28
+ * This header is generated by licensify (https://github.com/twada/licensify)
29
+ */
30
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.FormStorage = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
31
+ 'use strict';
32
+ var token = '%[a-f0-9]{2}';
33
+ var singleMatcher = new RegExp(token, 'gi');
34
+ var multiMatcher = new RegExp('(' + token + ')+', 'gi');
35
+
36
+ function decodeComponents(components, split) {
37
+ try {
38
+ // Try to decode the entire string first
39
+ return decodeURIComponent(components.join(''));
40
+ } catch (err) {
41
+ // Do nothing
42
+ }
43
+
44
+ if (components.length === 1) {
45
+ return components;
46
+ }
47
+
48
+ split = split || 1;
49
+
50
+ // Split the array in 2 parts
51
+ var left = components.slice(0, split);
52
+ var right = components.slice(split);
53
+
54
+ return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right));
55
+ }
56
+
57
+ function decode(input) {
58
+ try {
59
+ return decodeURIComponent(input);
60
+ } catch (err) {
61
+ var tokens = input.match(singleMatcher);
62
+
63
+ for (var i = 1; i < tokens.length; i++) {
64
+ input = decodeComponents(tokens, i).join('');
65
+
66
+ tokens = input.match(singleMatcher);
67
+ }
68
+
69
+ return input;
70
+ }
71
+ }
72
+
73
+ function customDecodeURIComponent(input) {
74
+ // Keep track of all the replacements and prefill the map with the `BOM`
75
+ var replaceMap = {
76
+ '%FE%FF': '\uFFFD\uFFFD',
77
+ '%FF%FE': '\uFFFD\uFFFD'
78
+ };
79
+
80
+ var match = multiMatcher.exec(input);
81
+ while (match) {
82
+ try {
83
+ // Decode as big chunks as possible
84
+ replaceMap[match[0]] = decodeURIComponent(match[0]);
85
+ } catch (err) {
86
+ var result = decode(match[0]);
87
+
88
+ if (result !== match[0]) {
89
+ replaceMap[match[0]] = result;
90
+ }
91
+ }
92
+
93
+ match = multiMatcher.exec(input);
94
+ }
95
+
96
+ // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else
97
+ replaceMap['%C2'] = '\uFFFD';
98
+
99
+ var entries = Object.keys(replaceMap);
100
+
101
+ for (var i = 0; i < entries.length; i++) {
102
+ // Replace all decoded components
103
+ var key = entries[i];
104
+ input = input.replace(new RegExp(key, 'g'), replaceMap[key]);
105
+ }
106
+
107
+ return input;
108
+ }
109
+
110
+ module.exports = function (encodedURI) {
111
+ if (typeof encodedURI !== 'string') {
112
+ throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`');
113
+ }
114
+
115
+ try {
116
+ encodedURI = encodedURI.replace(/\+/g, ' ');
117
+
118
+ // Try the built in decoder first
119
+ return decodeURIComponent(encodedURI);
120
+ } catch (err) {
121
+ // Fallback to a more advanced decoder
122
+ return customDecodeURIComponent(encodedURI);
123
+ }
124
+ };
125
+
126
+ },{}],2:[function(require,module,exports){
127
+ // get successful control from form and assemble into object
128
+ // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
129
+
130
+ // types which indicate a submit action and are not successful controls
131
+ // these will be ignored
132
+ var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;
133
+
134
+ // node names which could be successful controls
135
+ var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;
136
+
137
+ // Matches bracket notation.
138
+ var brackets = /(\[[^\[\]]*\])/g;
139
+
140
+ // serializes form fields
141
+ // @param form MUST be an HTMLForm element
142
+ // @param options is an optional argument to configure the serialization. Default output
143
+ // with no options specified is a url encoded string
144
+ // - hash: [true | false] Configure the output type. If true, the output will
145
+ // be a js object.
146
+ // - serializer: [function] Optional serializer function to override the default one.
147
+ // The function takes 3 arguments (result, key, value) and should return new result
148
+ // hash and url encoded str serializers are provided with this module
149
+ // - disabled: [true | false]. If true serialize disabled fields.
150
+ // - empty: [true | false]. If true serialize empty fields
151
+ function serialize(form, options) {
152
+ if (typeof options != 'object') {
153
+ options = { hash: !!options };
154
+ }
155
+ else if (options.hash === undefined) {
156
+ options.hash = true;
157
+ }
158
+
159
+ var result = (options.hash) ? {} : '';
160
+ var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);
161
+
162
+ var elements = form && form.elements ? form.elements : [];
163
+
164
+ //Object store each radio and set if it's empty or not
165
+ var radio_store = Object.create(null);
166
+
167
+ for (var i=0 ; i<elements.length ; ++i) {
168
+ var element = elements[i];
169
+
170
+ // ingore disabled fields
171
+ if ((!options.disabled && element.disabled) || !element.name) {
172
+ continue;
173
+ }
174
+ // ignore anyhting that is not considered a success field
175
+ if (!k_r_success_contrls.test(element.nodeName) ||
176
+ k_r_submitter.test(element.type)) {
177
+ continue;
178
+ }
179
+
180
+ var key = element.name;
181
+ var val = element.value;
182
+
183
+ // we can't just use element.value for checkboxes cause some browsers lie to us
184
+ // they say "on" for value when the box isn't checked
185
+ if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
186
+ val = undefined;
187
+ }
188
+
189
+ // If we want empty elements
190
+ if (options.empty) {
191
+ // for checkbox
192
+ if (element.type === 'checkbox' && !element.checked) {
193
+ val = '';
194
+ }
195
+
196
+ // for radio
197
+ if (element.type === 'radio') {
198
+ if (!radio_store[element.name] && !element.checked) {
199
+ radio_store[element.name] = false;
200
+ }
201
+ else if (element.checked) {
202
+ radio_store[element.name] = true;
203
+ }
204
+ }
205
+
206
+ // if options empty is true, continue only if its radio
207
+ if (val == undefined && element.type == 'radio') {
208
+ continue;
209
+ }
210
+ }
211
+ else {
212
+ // value-less fields are ignored unless options.empty is true
213
+ if (!val) {
214
+ continue;
215
+ }
216
+ }
217
+
218
+ // multi select boxes
219
+ if (element.type === 'select-multiple') {
220
+ val = [];
221
+
222
+ var selectOptions = element.options;
223
+ var isSelectedOptions = false;
224
+ for (var j=0 ; j<selectOptions.length ; ++j) {
225
+ var option = selectOptions[j];
226
+ var allowedEmpty = options.empty && !option.value;
227
+ var hasValue = (option.value || allowedEmpty);
228
+ if (option.selected && hasValue) {
229
+ isSelectedOptions = true;
230
+
231
+ // If using a hash serializer be sure to add the
232
+ // correct notation for an array in the multi-select
233
+ // context. Here the name attribute on the select element
234
+ // might be missing the trailing bracket pair. Both names
235
+ // "foo" and "foo[]" should be arrays.
236
+ if (options.hash && key.slice(key.length - 2) !== '[]') {
237
+ result = serializer(result, key + '[]', option.value);
238
+ }
239
+ else {
240
+ result = serializer(result, key, option.value);
241
+ }
242
+ }
243
+ }
244
+
245
+ // Serialize if no selected options and options.empty is true
246
+ if (!isSelectedOptions && options.empty) {
247
+ result = serializer(result, key, '');
248
+ }
249
+
250
+ continue;
251
+ }
252
+
253
+ result = serializer(result, key, val);
254
+ }
255
+
256
+ // Check for all empty radio buttons and serialize them with key=""
257
+ if (options.empty) {
258
+ for (var key in radio_store) {
259
+ if (!radio_store[key]) {
260
+ result = serializer(result, key, '');
261
+ }
262
+ }
263
+ }
264
+
265
+ return result;
266
+ }
267
+
268
+ function parse_keys(string) {
269
+ var keys = [];
270
+ var prefix = /^([^\[\]]*)/;
271
+ var children = new RegExp(brackets);
272
+ var match = prefix.exec(string);
273
+
274
+ if (match[1]) {
275
+ keys.push(match[1]);
276
+ }
277
+
278
+ while ((match = children.exec(string)) !== null) {
279
+ keys.push(match[1]);
280
+ }
281
+
282
+ return keys;
283
+ }
284
+
285
+ function hash_assign(result, keys, value) {
286
+ if (keys.length === 0) {
287
+ result = value;
288
+ return result;
289
+ }
290
+
291
+ var key = keys.shift();
292
+ var between = key.match(/^\[(.+?)\]$/);
293
+
294
+ if (key === '[]') {
295
+ result = result || [];
296
+
297
+ if (Array.isArray(result)) {
298
+ result.push(hash_assign(null, keys, value));
299
+ }
300
+ else {
301
+ // This might be the result of bad name attributes like "[][foo]",
302
+ // in this case the original `result` object will already be
303
+ // assigned to an object literal. Rather than coerce the object to
304
+ // an array, or cause an exception the attribute "_values" is
305
+ // assigned as an array.
306
+ result._values = result._values || [];
307
+ result._values.push(hash_assign(null, keys, value));
308
+ }
309
+
310
+ return result;
311
+ }
312
+
313
+ // Key is an attribute name and can be assigned directly.
314
+ if (!between) {
315
+ result[key] = hash_assign(result[key], keys, value);
316
+ }
317
+ else {
318
+ var string = between[1];
319
+ // +var converts the variable into a number
320
+ // better than parseInt because it doesn't truncate away trailing
321
+ // letters and actually fails if whole thing is not a number
322
+ var index = +string;
323
+
324
+ // If the characters between the brackets is not a number it is an
325
+ // attribute name and can be assigned directly.
326
+ if (isNaN(index)) {
327
+ result = result || {};
328
+ result[string] = hash_assign(result[string], keys, value);
329
+ }
330
+ else {
331
+ result = result || [];
332
+ result[index] = hash_assign(result[index], keys, value);
333
+ }
334
+ }
335
+
336
+ return result;
337
+ }
338
+
339
+ // Object/hash encoding serializer.
340
+ function hash_serializer(result, key, value) {
341
+ var matches = key.match(brackets);
342
+
343
+ // Has brackets? Use the recursive assignment function to walk the keys,
344
+ // construct any missing objects in the result tree and make the assignment
345
+ // at the end of the chain.
346
+ if (matches) {
347
+ var keys = parse_keys(key);
348
+ hash_assign(result, keys, value);
349
+ }
350
+ else {
351
+ // Non bracket notation can make assignments directly.
352
+ var existing = result[key];
353
+
354
+ // If the value has been assigned already (for instance when a radio and
355
+ // a checkbox have the same name attribute) convert the previous value
356
+ // into an array before pushing into it.
357
+ //
358
+ // NOTE: If this requirement were removed all hash creation and
359
+ // assignment could go through `hash_assign`.
360
+ if (existing) {
361
+ if (!Array.isArray(existing)) {
362
+ result[key] = [ existing ];
363
+ }
364
+
365
+ result[key].push(value);
366
+ }
367
+ else {
368
+ result[key] = value;
369
+ }
370
+ }
371
+
372
+ return result;
373
+ }
374
+
375
+ // urlform encoding serializer
376
+ function str_serialize(result, key, value) {
377
+ // encode newlines as \r\n cause the html spec says so
378
+ value = value.replace(/(\r)?\n/g, '\r\n');
379
+ value = encodeURIComponent(value);
380
+
381
+ // spaces should be '+' rather than '%20'.
382
+ value = value.replace(/%20/g, '+');
383
+ return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
384
+ }
385
+
386
+ module.exports = serialize;
387
+
388
+ },{}],3:[function(require,module,exports){
389
+ 'use strict';
390
+
391
+ var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
392
+
393
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
394
+
395
+ var encodeURIComponent = function (str) {
396
+ return encodeURIComponent(str).replace(/[!'()*]/g, function (x) {
397
+ return "%" + x.charCodeAt(0).toString(16).toUpperCase();
398
+ });
399
+ }
400
+
401
+ var decodeComponent = require('decode-uri-component');
402
+
403
+ function encoderForArrayFormat(options) {
404
+ switch (options.arrayFormat) {
405
+ case 'index':
406
+ return function (key, value, index) {
407
+ return value === null ? [encode(key, options), '[', index, ']'].join('') : [encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join('');
408
+ };
409
+ case 'bracket':
410
+ return function (key, value) {
411
+ return value === null ? [encode(key, options), '[]'].join('') : [encode(key, options), '[]=', encode(value, options)].join('');
412
+ };
413
+ default:
414
+ return function (key, value) {
415
+ return value === null ? encode(key, options) : [encode(key, options), '=', encode(value, options)].join('');
416
+ };
417
+ }
418
+ }
419
+
420
+ function parserForArrayFormat(options) {
421
+ var result = void 0;
422
+
423
+ switch (options.arrayFormat) {
424
+ case 'index':
425
+ return function (key, value, accumulator) {
426
+ result = /\[(\d*)\]$/.exec(key);
427
+
428
+ key = key.replace(/\[\d*\]$/, '');
429
+
430
+ if (!result) {
431
+ accumulator[key] = value;
432
+ return;
433
+ }
434
+
435
+ if (accumulator[key] === undefined) {
436
+ accumulator[key] = {};
437
+ }
438
+
439
+ accumulator[key][result[1]] = value;
440
+ };
441
+ case 'bracket':
442
+ return function (key, value, accumulator) {
443
+ result = /(\[\])$/.exec(key);
444
+ key = key.replace(/\[\]$/, '');
445
+
446
+ if (!result) {
447
+ accumulator[key] = value;
448
+ return;
449
+ }
450
+
451
+ if (accumulator[key] === undefined) {
452
+ accumulator[key] = [value];
453
+ return;
454
+ }
455
+
456
+ accumulator[key] = [].concat(accumulator[key], value);
457
+ };
458
+ default:
459
+ return function (key, value, accumulator) {
460
+ if (accumulator[key] === undefined) {
461
+ accumulator[key] = value;
462
+ return;
463
+ }
464
+
465
+ accumulator[key] = [].concat(accumulator[key], value);
466
+ };
467
+ }
468
+ }
469
+
470
+ function encode(value, options) {
471
+ if (options.encode) {
472
+ return options.strict ? strictUriEncode(value) : encodeURIComponent(value);
473
+ }
474
+
475
+ return value;
476
+ }
477
+
478
+ function decode(value, options) {
479
+ if (options.decode) {
480
+ return decodeComponent(value);
481
+ }
482
+
483
+ return value;
484
+ }
485
+
486
+ function keysSorter(input) {
487
+ if (Array.isArray(input)) {
488
+ return input.sort();
489
+ }
490
+
491
+ if ((typeof input === 'undefined' ? 'undefined' : _typeof(input)) === 'object') {
492
+ return keysSorter(Object.keys(input)).sort(function (a, b) {
493
+ return Number(a) - Number(b);
494
+ }).map(function (key) {
495
+ return input[key];
496
+ });
497
+ }
498
+
499
+ return input;
500
+ }
501
+
502
+ function extract(input) {
503
+ var queryStart = input.indexOf('?');
504
+ if (queryStart === -1) {
505
+ return '';
506
+ }
507
+ return input.slice(queryStart + 1);
508
+ }
509
+
510
+ function parse(input, options) {
511
+ options = Object.assign({ decode: true, arrayFormat: 'none' }, options);
512
+
513
+ var formatter = parserForArrayFormat(options);
514
+
515
+ // Create an object with no prototype
516
+ var ret = Object.create(null);
517
+
518
+ if (typeof input !== 'string') {
519
+ return ret;
520
+ }
521
+
522
+ input = input.trim().replace(/^[?#&]/, '');
523
+
524
+ if (!input) {
525
+ return ret;
526
+ }
527
+
528
+ var _iteratorNormalCompletion = true;
529
+ var _didIteratorError = false;
530
+ var _iteratorError = undefined;
531
+
532
+ try {
533
+ for (var _iterator = input.split('&')[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
534
+ var param = _step.value;
535
+
536
+ var _param$replace$split = param.replace(/\+/g, ' ').split('='),
537
+ _param$replace$split2 = _slicedToArray(_param$replace$split, 2),
538
+ key = _param$replace$split2[0],
539
+ value = _param$replace$split2[1];
540
+
541
+ // Missing `=` should be `null`:
542
+ // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
543
+
544
+
545
+ value = value === undefined ? null : decode(value, options);
546
+
547
+ formatter(decode(key, options), value, ret);
548
+ }
549
+ } catch (err) {
550
+ _didIteratorError = true;
551
+ _iteratorError = err;
552
+ } finally {
553
+ try {
554
+ if (!_iteratorNormalCompletion && _iterator.return) {
555
+ _iterator.return();
556
+ }
557
+ } finally {
558
+ if (_didIteratorError) {
559
+ throw _iteratorError;
560
+ }
561
+ }
562
+ }
563
+
564
+ return Object.keys(ret).sort().reduce(function (result, key) {
565
+ var value = ret[key];
566
+ if (Boolean(value) && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && !Array.isArray(value)) {
567
+ // Sort object keys, not values
568
+ result[key] = keysSorter(value);
569
+ } else {
570
+ result[key] = value;
571
+ }
572
+
573
+ return result;
574
+ }, Object.create(null));
575
+ }
576
+
577
+ exports.extract = extract;
578
+ exports.parse = parse;
579
+
580
+ exports.stringify = function (obj, options) {
581
+ var defaults = {
582
+ encode: true,
583
+ strict: true,
584
+ arrayFormat: 'none'
585
+ };
586
+
587
+ options = Object.assign(defaults, options);
588
+
589
+ if (options.sort === false) {
590
+ options.sort = function () {};
591
+ }
592
+
593
+ var formatter = encoderForArrayFormat(options);
594
+
595
+ return obj ? Object.keys(obj).sort(options.sort).map(function (key) {
596
+ var value = obj[key];
597
+
598
+ if (value === undefined) {
599
+ return '';
600
+ }
601
+
602
+ if (value === null) {
603
+ return encode(key, options);
604
+ }
605
+
606
+ if (Array.isArray(value)) {
607
+ var result = [];
608
+
609
+ var _iteratorNormalCompletion2 = true;
610
+ var _didIteratorError2 = false;
611
+ var _iteratorError2 = undefined;
612
+
613
+ try {
614
+ for (var _iterator2 = value.slice()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
615
+ var value2 = _step2.value;
616
+
617
+ if (value2 === undefined) {
618
+ continue;
619
+ }
620
+
621
+ result.push(formatter(key, value2, result.length));
622
+ }
623
+ } catch (err) {
624
+ _didIteratorError2 = true;
625
+ _iteratorError2 = err;
626
+ } finally {
627
+ try {
628
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
629
+ _iterator2.return();
630
+ }
631
+ } finally {
632
+ if (_didIteratorError2) {
633
+ throw _iteratorError2;
634
+ }
635
+ }
636
+ }
637
+
638
+ return result.join('&');
639
+ }
640
+
641
+ return encode(key, options) + '=' + encode(value, options);
642
+ }).filter(function (x) {
643
+ return x.length > 0;
644
+ }).join('&') : '';
645
+ };
646
+
647
+ exports.parseUrl = function (input, options) {
648
+ return {
649
+ url: input.split('?')[0] || '',
650
+ query: parse(extract(input), options)
651
+ };
652
+ };
653
+ },{"decode-uri-component":1}],4:[function(require,module,exports){
654
+ 'use strict';
655
+
656
+ Object.defineProperty(exports, "__esModule", {
657
+ value: true
658
+ });
659
+
660
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
661
+
662
+ var _formSerialize = require('form-serialize');
663
+
664
+ var _formSerialize2 = _interopRequireDefault(_formSerialize);
665
+
666
+ var _queryStringEs = require('query-string-es5');
667
+
668
+ var _queryStringEs2 = _interopRequireDefault(_queryStringEs);
669
+
670
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
671
+
672
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
673
+
674
+ var defaults = {
675
+ name: 'form',
676
+ ignores: [],
677
+ includes: [],
678
+ checkbox: null
679
+ };
680
+
681
+ var FormStorage = function () {
682
+ function FormStorage(selector, opt) {
683
+ _classCallCheck(this, FormStorage);
684
+
685
+ this.ele = document.querySelector(selector);
686
+ this.opt = Object.assign({}, defaults, opt);
687
+ if (this.opt.checkbox) {
688
+ this.checkbox = document.querySelector(this.opt.checkbox);
689
+ this.setCheckbox();
690
+ this.apply();
691
+ }
692
+ }
693
+
694
+ _createClass(FormStorage, [{
695
+ key: 'save',
696
+ value: function save() {
697
+ var str = (0, _formSerialize2.default)(this.ele);
698
+ window.localStorage.setItem(this.opt.name, str);
699
+ }
700
+ }, {
701
+ key: 'clear',
702
+ value: function clear() {
703
+ window.localStorage.removeItem(this.opt.name);
704
+ }
705
+ }, {
706
+ key: 'setCheckbox',
707
+ value: function setCheckbox() {
708
+ var _this = this;
709
+
710
+ this.ele.addEventListener('submit', function () {
711
+ if (_this.checkbox.checked) {
712
+ _this.save();
713
+ } else {
714
+ _this.clear();
715
+ }
716
+ });
717
+ }
718
+ }, {
719
+ key: 'getState',
720
+ value: function getState() {
721
+ return (0, _formSerialize2.default)(this.ele);
722
+ }
723
+ }, {
724
+ key: 'applyState',
725
+ value: function applyState(str) {
726
+ var _this2 = this;
727
+
728
+ var _opt = this.opt,
729
+ ignores = _opt.ignores,
730
+ includes = _opt.includes;
731
+
732
+ var obj = _queryStringEs2.default.parse(str.replace(/^"(.*)"$/, "$1"));
733
+
734
+ var _loop = function _loop(key) {
735
+ var flag = false;
736
+ var target = _this2.ele.querySelector('[name="' + key + '"]');
737
+ var targets = _this2.ele.querySelectorAll('[name="' + key + '"]');
738
+
739
+ if (!target) {
740
+ return 'continue';
741
+ }
742
+
743
+ ignores.forEach(function (ignore) {
744
+ if (target.matches(ignore)) {
745
+ flag = true;
746
+ return false;
747
+ }
748
+ });
749
+
750
+ if (flag) {
751
+ return 'continue';
752
+ }
753
+
754
+ if (includes.length > 0) {
755
+ flag = true;
756
+ includes.forEach(function (include) {
757
+ if (target.matches(include)) {
758
+ flag = false;
759
+ return false;
760
+ }
761
+ });
762
+ if (flag) {
763
+ return 'continue';
764
+ }
765
+ }
766
+
767
+ if (targets && targets.length > 1) {
768
+ var arr = obj[key];
769
+ [].forEach.call(targets, function (tar, index) {
770
+ if (tar.type === 'checkbox') {
771
+ if (arr.forEach) {
772
+ arr.forEach(function (item) {
773
+ if (item === tar.value) {
774
+ tar.checked = true;
775
+ }
776
+ });
777
+ } else {
778
+ if (arr === tar.value) {
779
+ tar.checked = true;
780
+ }
781
+ }
782
+ } else if (tar.type === 'radio') {
783
+ if (tar.value === arr) {
784
+ tar.checked = true;
785
+ }
786
+ }
787
+ });
788
+ return 'continue';
789
+ }
790
+
791
+ if (target.type === 'radio' || target.type === 'checkbox') {
792
+ if (obj[key] === target.value) {
793
+ target.checked = true;
794
+ }
795
+ } else {
796
+ target.value = obj[key];
797
+ }
798
+ };
799
+
800
+ for (var key in obj) {
801
+ var _ret = _loop(key);
802
+
803
+ if (_ret === 'continue') continue;
804
+ }
805
+ }
806
+ }, {
807
+ key: 'apply',
808
+ value: function apply() {
809
+ var str = window.localStorage.getItem(this.opt.name);
810
+ if (!str) {
811
+ return;
812
+ }
813
+ this.applyState(str);
814
+ }
815
+ }]);
816
+
817
+ return FormStorage;
818
+ }();
819
+
820
+ exports.default = FormStorage;
821
+ module.exports = exports['default'];
822
+
823
+ },{"form-serialize":2,"query-string-es5":3}]},{},[4])(4)
824
+ });