@@ -1,2 +1,15 @@ |
||
1 | 1 |
.scenario-import { |
2 |
+ .agent-import-list { |
|
3 |
+ .agent-import { |
|
4 |
+ margin-bottom: 20px; |
|
5 |
+ |
|
6 |
+ .instructions { |
|
7 |
+ margin-bottom: 10px; |
|
8 |
+ } |
|
9 |
+ |
|
10 |
+ .current { |
|
11 |
+ font-weight: bold; |
|
12 |
+ } |
|
13 |
+ } |
|
14 |
+ } |
|
2 | 15 |
} |
@@ -19,13 +19,13 @@ module Agents |
||
19 | 19 |
Your event can provide any of the following optional parameters or you can provide defaults: |
20 | 20 |
|
21 | 21 |
* `device` - your user's device name to send the message directly to that device, rather than all of the user's devices |
22 |
- * `title` or `subject` - your notifications's title |
|
22 |
+ * `title` or `subject` - your notification's title |
|
23 | 23 |
* `url` - a supplementary URL to show with your message - `512` Character Limit |
24 | 24 |
* `url_title` - a title for your supplementary URL, otherwise just the URL is shown - `100` Character Limit |
25 | 25 |
* `priority` - send as `-1` to always send as a quiet notification, `0` is default, `1` to display as high-priority and bypass the user's quiet hours, or `2` for emergency priority: [Please read Pushover Docs on Emergency Priority](https://pushover.net/api#priority) |
26 | 26 |
* `sound` - the name of one of the sounds supported by device clients to override the user's default sound choice. [See PushOver docs for sound options.](https://pushover.net/api#sounds) |
27 |
- * `retry` - Requred for emergency priority - Specifies how often (in seconds) the Pushover servers will send the same notification to the user. Minimum value: `30` |
|
28 |
- * `expire` - Requred for emergency priority - Specifies how many seconds your notification will continue to be retried for (every retry seconds). Maximum value: `86400` |
|
27 |
+ * `retry` - Required for emergency priority - Specifies how often (in seconds) the Pushover servers will send the same notification to the user. Minimum value: `30` |
|
28 |
+ * `expire` - Required for emergency priority - Specifies how many seconds your notification will continue to be retried for (every retry seconds). Maximum value: `86400` |
|
29 | 29 |
|
30 | 30 |
Your event can also pass along a timestamp parameter: |
31 | 31 |
|
@@ -42,10 +42,10 @@ module Agents |
||
42 | 42 |
'title' => '', |
43 | 43 |
'url' => '', |
44 | 44 |
'url_title' => '', |
45 |
- 'priority' => 0, |
|
45 |
+ 'priority' => '0', |
|
46 | 46 |
'sound' => 'pushover', |
47 |
- 'retry' => 0, |
|
48 |
- 'expire' => 0, |
|
47 |
+ 'retry' => '0', |
|
48 |
+ 'expire' => '0', |
|
49 | 49 |
'expected_receive_period_in_days' => '1' |
50 | 50 |
} |
51 | 51 |
end |
@@ -102,6 +102,5 @@ module Agents |
||
102 | 102 |
response = HTTParty.post(API_URL, :query => post_params) |
103 | 103 |
puts response |
104 | 104 |
end |
105 |
- |
|
106 | 105 |
end |
107 | 106 |
end |
@@ -77,7 +77,7 @@ |
||
77 | 77 |
<div class="col-md-12"> |
78 | 78 |
<div class="form-group"> |
79 | 79 |
<%= f.label :options %> |
80 |
- <textarea rows="10" id="agent_options" name="agent[options]" class="form-control live-json-editor <%= (@agent.new_record? && @agent.options == {}) ? "showing-default" : "" %>"> |
|
80 |
+ <textarea rows="15" id="agent_options" name="agent[options]" class="form-control live-json-editor <%= (@agent.new_record? && @agent.options == {}) ? "showing-default" : "" %>"> |
|
81 | 81 |
<%= Utils.jsonify((@agent.new_record? && @agent.options == {}) ? @agent.default_options : @agent.options) %> |
82 | 82 |
</textarea> |
83 | 83 |
</div> |
@@ -104,7 +104,7 @@ |
||
104 | 104 |
|
105 | 105 |
<div class='row'> |
106 | 106 |
<div class="col-md-12"> |
107 |
- <%= f.submit :class => "btn btn-primary" %> |
|
107 |
+ <%= f.submit "Save", :class => "btn btn-primary" %> |
|
108 | 108 |
</div> |
109 | 109 |
</div> |
110 | 110 |
|
@@ -31,18 +31,22 @@ |
||
31 | 31 |
|
32 | 32 |
<script> |
33 | 33 |
var agentPaths = {}; |
34 |
- <% if current_user -%> |
|
35 |
- var myAgents = <%= Utils.jsonify(current_user.agents.select([:name, :id, :schedule]).inject({}) {|m, a| m[a.name] = agent_path(a); m }) %>; |
|
34 |
+ var agentNames = []; |
|
35 |
+ <% if current_user.present? -%> |
|
36 |
+ var myAgents = <%= Utils.jsonify(current_user.agents.pluck(:name, :id).inject({}) {|m, a| m[a.first] = agent_path(a.last); m }) %>; |
|
37 |
+ var myScenarios = <%= Utils.jsonify(current_user.scenarios.pluck(:name, :id).inject({}) {|m, s| m[s.first + " Scenario"] = scenario_path(s.last); m }) %>; |
|
36 | 38 |
$.extend(agentPaths, myAgents); |
39 |
+ $.extend(agentPaths, myScenarios); |
|
40 |
+ agentPaths["All Agents Index"] = <%= Utils.jsonify agents_path %>; |
|
41 |
+ agentPaths["New Agent"] = <%= Utils.jsonify new_agent_path %>; |
|
42 |
+ agentPaths["Account"] = <%= Utils.jsonify edit_user_registration_path %>; |
|
43 |
+ agentPaths["Events Index"] = <%= Utils.jsonify events_path %>; |
|
44 |
+ agentPaths["View Agent Diagram"] = <%= Utils.jsonify diagram_agents_path %>; |
|
45 |
+ agentPaths["Run Event Propagation"] = { url: <%= Utils.jsonify propagate_agents_path %>, method: 'POST' }; |
|
46 |
+ |
|
47 |
+ |
|
48 |
+ $.each(agentPaths, function(name, v) { agentNames.push(name); }); |
|
37 | 49 |
<% end -%> |
38 |
- agentPaths["All Agents Index"] = <%= Utils.jsonify agents_path %>; |
|
39 |
- agentPaths["New Agent"] = <%= Utils.jsonify new_agent_path %>; |
|
40 |
- agentPaths["Account"] = <%= Utils.jsonify edit_user_registration_path %>; |
|
41 |
- agentPaths["Events Index"] = <%= Utils.jsonify events_path %>; |
|
42 |
- agentPaths["View Agent Diagram"] = <%= Utils.jsonify diagram_agents_path %>; |
|
43 |
- agentPaths["Run Event Propagation"] = { url: <%= Utils.jsonify propagate_agents_path %>, method: 'POST' }; |
|
44 |
- var agentNames = []; |
|
45 |
- $.each(agentPaths, function(name, v) { agentNames.push(name); }); |
|
46 | 50 |
</script> |
47 | 51 |
</body> |
48 | 52 |
</html> |
@@ -7,10 +7,9 @@ |
||
7 | 7 |
</div> |
8 | 8 |
|
9 | 9 |
<div class='row'> |
10 |
- <blockquote> |
|
11 |
- You can import Scenarios, either from a <code>.json</code> file, or via a public Scenario URL. When you |
|
12 |
- import a Scenario, Huginn will keep track of where it came from and later let you update it. |
|
13 |
- </blockquote> |
|
10 |
+ <blockquote>You can import Scenarios, either from a <code>.json</code> file, or via a public |
|
11 |
+ Scenario URL. When you import a Scenario, Huginn will keep track of where it came from and |
|
12 |
+ later let you update it.</blockquote> |
|
14 | 13 |
</div> |
15 | 14 |
|
16 | 15 |
<div class='row'> |
@@ -22,8 +22,10 @@ |
||
22 | 22 |
<div class="page-header"> |
23 | 23 |
<h2> |
24 | 24 |
<%= @scenario_import.parsed_data["name"] %> |
25 |
- <span class='text-muted'>(<%= pluralize @scenario_import.parsed_data["agents"].length, "Agent" %> |
|
26 |
- ; exported <%= time_ago_in_words Time.parse(@scenario_import.parsed_data["exported_at"]) %> ago)</span> |
|
25 |
+ <span class='text-muted'> |
|
26 |
+ (<%= pluralize @scenario_import.parsed_data["agents"].length, "Agent" %>; |
|
27 |
+ exported <%= time_ago_in_words Time.parse(@scenario_import.parsed_data["exported_at"]) %> ago) |
|
28 |
+ </span> |
|
27 | 29 |
</h2> |
28 | 30 |
</div> |
29 | 31 |
|
@@ -48,7 +50,7 @@ |
||
48 | 50 |
</h3> |
49 | 51 |
|
50 | 52 |
<% if agent_diff.agent_exists? %> |
51 |
- <div> |
|
53 |
+ <div class="instructions"> |
|
52 | 54 |
This Agent exists in your Huginn system. |
53 | 55 |
|
54 | 56 |
<% if agent_diff.requires_merge? %> |
@@ -105,7 +107,7 @@ |
||
105 | 107 |
</div> |
106 | 108 |
|
107 | 109 |
<div class='col-md-6'> |
108 |
- <textarea name="scenario_import[merges][<%= index %>][options]" rows='10' class="form-control live-json-editor"> |
|
110 |
+ <textarea name="scenario_import[merges][<%= index %>][options]" rows='15' class="form-control live-json-editor"> |
|
109 | 111 |
<%= Utils.pretty_jsonify(agent_diff.options.updated) %> |
110 | 112 |
</textarea> |
111 | 113 |
</div> |
@@ -7,7 +7,8 @@ |
||
7 | 7 |
</h2> |
8 | 8 |
</div> |
9 | 9 |
|
10 |
- <blockquote>Scenarios are named groups of Agents. Scenarios allow you to organize your agents, and to export sets of Agents for sharing.</blockquote> |
|
10 |
+ <blockquote>Scenarios are named groups of Agents. Scenarios allow you to organize your agents, |
|
11 |
+ and to import and export sets of Agents to share.</blockquote> |
|
11 | 12 |
|
12 | 13 |
<table class='table table-striped'> |
13 | 14 |
<tr> |
@@ -2,7 +2,7 @@ |
||
2 | 2 |
<div class='row'> |
3 | 3 |
<div class='col-md-12'> |
4 | 4 |
<div class="page-header"> |
5 |
- <h2><%= "Public" if @scenario.public? %> Scenario <span class='label label-info scenario'><%= @scenario.name %></span></h2> |
|
5 |
+ <h2><span class='label label-info scenario'><%= @scenario.name %></span> <%= "Public" if @scenario.public? %> Scenario</h2> |
|
6 | 6 |
</div> |
7 | 7 |
|
8 | 8 |
<% if @scenario.description.present? %> |
@@ -1,5 +1,5 @@ |
||
1 | 1 |
/* |
2 |
- Copyright (c) 2013, Andrew Cantino |
|
2 |
+ Copyright (c) 2014, Andrew Cantino |
|
3 | 3 |
Copyright (c) 2009, Andrew Cantino & Kyle Maxwell |
4 | 4 |
|
5 | 5 |
Permission is hereby granted, free of charge, to any person obtaining a copy |
@@ -23,8 +23,8 @@ |
||
23 | 23 |
|
24 | 24 |
|
25 | 25 |
|
26 |
- You will probably need to tell the editor where to find its add and delete images. In your |
|
27 |
- code before you make the editor, do something like this: |
|
26 |
+ You will probably need to tell the editor where to find its 'add' and 'delete' images. In your |
|
27 |
+ code, before you make the editor, do something like this: |
|
28 | 28 |
JSONEditor.prototype.ADD_IMG = '/javascripts/jsoneditor/add.png'; |
29 | 29 |
JSONEditor.prototype.DELETE_IMG = '/javascripts/jsoneditor/delete.png'; |
30 | 30 |
|
@@ -36,504 +36,529 @@ |
||
36 | 36 |
*/ |
37 | 37 |
|
38 | 38 |
|
39 |
-function JSONEditorBase(options) { |
|
40 |
- if (!options) options = {}; |
|
41 |
- this.builderShowing = true; |
|
42 |
- this.ADD_IMG = options.ADD_IMG || 'lib/images/add.png'; |
|
43 |
- this.DELETE_IMG = options.DELETE_IMG || 'lib/images/delete.png'; |
|
44 |
- this.functionButtonsEnabled = false; |
|
45 |
- this._doTruncation = true; |
|
46 |
- this._showWipe = options.showWipe; |
|
47 |
-} |
|
48 |
- |
|
49 |
-function JSONEditor(wrapped, width, height) { |
|
50 |
- this.history = []; |
|
51 |
- this.historyPointer = -1; |
|
52 |
- if (wrapped == null || (wrapped.get && wrapped.get(0) == null)) throw "Must provide an element to wrap."; |
|
53 |
- var width = width || 600; |
|
54 |
- var height = height || 300; |
|
55 |
- this.wrapped = $(wrapped); |
|
56 |
- |
|
57 |
- this.wrapped.wrap('<div class="json-editor"></div>'); |
|
58 |
- this.container = $(this.wrapped.parent()); |
|
59 |
- this.container.width(width).height(height); |
|
60 |
- this.wrapped.width(width).height(height); |
|
61 |
- this.wrapped.hide(); |
|
62 |
- this.container.css("position", "relative"); |
|
63 |
- this.doAutoFocus = false; |
|
64 |
- this.editingUnfocused(); |
|
65 |
- |
|
66 |
- this.rebuild(); |
|
67 |
- var self = this; |
|
68 |
- this.container.focus(function(){ |
|
69 |
- $(this).children('textarea').height(self.container.height() - self.functionButtons.height() - 5); |
|
70 |
- $(this).children('.builder').height(self.container.height() - self.functionButtons.height() - 10); |
|
71 |
- }); |
|
72 |
- |
|
73 |
- return this; |
|
74 |
-} |
|
75 |
-JSONEditor.prototype = new JSONEditorBase(); |
|
76 |
- |
|
77 |
-JSONEditor.prototype.braceUI = function(key, struct) { |
|
78 |
- var self = this; |
|
79 |
- return $('<a class="icon" href="#"><strong>{</strong></a>').click(function(e) { |
|
80 |
- struct[key] = { "??": struct[key] }; |
|
81 |
- self.doAutoFocus = true; |
|
82 |
- self.rebuild(); |
|
83 |
- return false; |
|
84 |
- }); |
|
85 |
-}; |
|
86 |
- |
|
87 |
-JSONEditor.prototype.bracketUI = function(key, struct) { |
|
88 |
- var self = this; |
|
89 |
- return $('<a class="icon" href="#"><strong>[</a>').click(function(e) { |
|
90 |
- struct[key] = [ struct[key] ]; |
|
91 |
- self.doAutoFocus = true; |
|
92 |
- self.rebuild(); |
|
93 |
- return false; |
|
94 |
- }); |
|
95 |
-}; |
|
96 |
- |
|
97 |
-JSONEditor.prototype.deleteUI = function(key, struct, fullDelete) { |
|
98 |
- var self = this; |
|
99 |
- return $('<a class="icon" href="#" title="delete"><img src="' + this.DELETE_IMG + '" border=0/></a>').click(function(e) { |
|
100 |
- if (!fullDelete) { |
|
101 |
- var didSomething = false; |
|
102 |
- if (struct[key] instanceof Array) { |
|
103 |
- if(struct[key].length > 0) { |
|
104 |
- struct[key] = struct[key][0]; |
|
105 |
- didSomething = true; |
|
39 |
+(function() { |
|
40 |
+ |
|
41 |
+ window.JSONEditor = (function() { |
|
42 |
+ |
|
43 |
+ function JSONEditor(wrapped, options) { |
|
44 |
+ if (options == null) { |
|
45 |
+ options = {}; |
|
46 |
+ } |
|
47 |
+ this.builderShowing = true; |
|
48 |
+ this.ADD_IMG || (this.ADD_IMG = options.ADD_IMG || 'lib/images/add.png'); |
|
49 |
+ this.DELETE_IMG || (this.DELETE_IMG = options.DELETE_IMG || 'lib/images/delete.png'); |
|
50 |
+ this.functionButtonsEnabled = false; |
|
51 |
+ this._doTruncation = true; |
|
52 |
+ this._showWipe = options.showWipe; |
|
53 |
+ this.history = []; |
|
54 |
+ this.historyPointer = -1; |
|
55 |
+ if (wrapped === null || (wrapped.get && wrapped.get(0) === null)) { |
|
56 |
+ throw "Must provide an element to wrap."; |
|
57 |
+ } |
|
58 |
+ this.wrapped = $(wrapped); |
|
59 |
+ this.wrapped.wrap('<div class="json-editor"></div>'); |
|
60 |
+ this.container = $(this.wrapped.parent()); |
|
61 |
+ this.wrapped.hide(); |
|
62 |
+ this.container.css("position", "relative"); |
|
63 |
+ this.doAutoFocus = false; |
|
64 |
+ this.editingUnfocused(); |
|
65 |
+ this.rebuild(); |
|
66 |
+ } |
|
67 |
+ |
|
68 |
+ JSONEditor.prototype.braceUI = function(key, struct) { |
|
69 |
+ var _this = this; |
|
70 |
+ return $('<a class="icon" href="#"><strong>{</strong></a>').click(function(e) { |
|
71 |
+ e.preventDefault(); |
|
72 |
+ struct[key] = { |
|
73 |
+ "??": struct[key] |
|
74 |
+ }; |
|
75 |
+ _this.doAutoFocus = true; |
|
76 |
+ return _this.rebuild(); |
|
77 |
+ }); |
|
78 |
+ }; |
|
79 |
+ |
|
80 |
+ JSONEditor.prototype.bracketUI = function(key, struct) { |
|
81 |
+ var _this = this; |
|
82 |
+ return $('<a class="icon" href="#"><strong>[</a>').click(function(e) { |
|
83 |
+ e.preventDefault(); |
|
84 |
+ struct[key] = [struct[key]]; |
|
85 |
+ _this.doAutoFocus = true; |
|
86 |
+ return _this.rebuild(); |
|
87 |
+ }); |
|
88 |
+ }; |
|
89 |
+ |
|
90 |
+ JSONEditor.prototype.deleteUI = function(key, struct, fullDelete) { |
|
91 |
+ var _this = this; |
|
92 |
+ return $("<a class='icon' href='#' title='delete'><img src='" + this.DELETE_IMG + "' border=0 /></a>").click(function(e) { |
|
93 |
+ var didSomething, subkey, subval, _ref; |
|
94 |
+ e.preventDefault(); |
|
95 |
+ if (!fullDelete) { |
|
96 |
+ didSomething = false; |
|
97 |
+ if (struct[key] instanceof Array) { |
|
98 |
+ if (struct[key].length > 0) { |
|
99 |
+ struct[key] = struct[key][0]; |
|
100 |
+ didSomething = true; |
|
101 |
+ } |
|
102 |
+ } else if (struct[key] instanceof Object) { |
|
103 |
+ _ref = struct[key]; |
|
104 |
+ for (subkey in _ref) { |
|
105 |
+ subval = _ref[subkey]; |
|
106 |
+ struct[key] = struct[key][subkey]; |
|
107 |
+ didSomething = true; |
|
108 |
+ break; |
|
109 |
+ } |
|
110 |
+ } |
|
111 |
+ if (didSomething) { |
|
112 |
+ _this.rebuild(); |
|
113 |
+ return; |
|
114 |
+ } |
|
106 | 115 |
} |
107 |
- } else if (struct[key] instanceof Object) { |
|
108 |
- for (var i in struct[key]) { |
|
109 |
- struct[key] = struct[key][i]; |
|
110 |
- didSomething = true; |
|
111 |
- break; |
|
116 |
+ if (struct instanceof Array) { |
|
117 |
+ struct.splice(key, 1); |
|
118 |
+ } else { |
|
119 |
+ delete struct[key]; |
|
120 |
+ } |
|
121 |
+ return _this.rebuild(); |
|
122 |
+ }); |
|
123 |
+ }; |
|
124 |
+ |
|
125 |
+ JSONEditor.prototype.wipeUI = function(key, struct) { |
|
126 |
+ var _this = this; |
|
127 |
+ return $('<a class="icon" href="#" title="wipe"><strong>W</strong></a>').click(function(e) { |
|
128 |
+ e.preventDefault(); |
|
129 |
+ if (struct instanceof Array) { |
|
130 |
+ struct.splice(key, 1); |
|
131 |
+ } else { |
|
132 |
+ delete struct[key]; |
|
133 |
+ } |
|
134 |
+ return _this.rebuild(); |
|
135 |
+ }); |
|
136 |
+ }; |
|
137 |
+ |
|
138 |
+ JSONEditor.prototype.addUI = function(struct) { |
|
139 |
+ var _this = this; |
|
140 |
+ return $("<a class='icon' href='#' title='add'><img src='" + this.ADD_IMG + "' border=0/></a>").click(function(e) { |
|
141 |
+ e.preventDefault(); |
|
142 |
+ if (struct instanceof Array) { |
|
143 |
+ struct.push('??'); |
|
144 |
+ } else { |
|
145 |
+ struct['??'] = '??'; |
|
146 |
+ } |
|
147 |
+ _this.doAutoFocus = true; |
|
148 |
+ return _this.rebuild(); |
|
149 |
+ }); |
|
150 |
+ }; |
|
151 |
+ |
|
152 |
+ JSONEditor.prototype.undo = function() { |
|
153 |
+ if (this.saveStateIfTextChanged()) { |
|
154 |
+ if (this.historyPointer > 0) { |
|
155 |
+ this.historyPointer -= 1; |
|
156 |
+ } |
|
157 |
+ return this.restore(); |
|
158 |
+ } |
|
159 |
+ }; |
|
160 |
+ |
|
161 |
+ JSONEditor.prototype.redo = function() { |
|
162 |
+ if (this.historyPointer + 1 < this.history.length) { |
|
163 |
+ if (this.saveStateIfTextChanged()) { |
|
164 |
+ this.historyPointer += 1; |
|
165 |
+ return this.restore(); |
|
112 | 166 |
} |
113 | 167 |
} |
114 |
- if (didSomething) { |
|
115 |
- self.rebuild(); |
|
168 |
+ }; |
|
169 |
+ |
|
170 |
+ JSONEditor.prototype.showBuilder = function() { |
|
171 |
+ if (this.checkJsonInText()) { |
|
172 |
+ this.setJsonFromText(); |
|
173 |
+ this.rebuild(); |
|
174 |
+ this.wrapped.hide(); |
|
175 |
+ this.builder.show(); |
|
176 |
+ return true; |
|
177 |
+ } else { |
|
178 |
+ alert("Sorry, there appears to be an error in your JSON input. Please fix it before continuing."); |
|
116 | 179 |
return false; |
117 | 180 |
} |
118 |
- } |
|
119 |
- if (struct instanceof Array) { |
|
120 |
- struct.splice(key, 1); |
|
121 |
- } else { |
|
122 |
- delete struct[key]; |
|
123 |
- } |
|
124 |
- self.rebuild(); |
|
125 |
- return false; |
|
126 |
- }); |
|
127 |
-}; |
|
128 |
- |
|
129 |
-JSONEditor.prototype.wipeUI = function(key, struct) { |
|
130 |
- var self = this; |
|
131 |
- return $('<a class="icon" href="#" title="wipe"><strong>W</strong></a>').click(function(e) { |
|
132 |
- if (struct instanceof Array) { |
|
133 |
- struct.splice(key, 1); |
|
134 |
- } else { |
|
135 |
- delete struct[key]; |
|
136 |
- } |
|
137 |
- self.rebuild(); |
|
138 |
- return false; |
|
139 |
- }); |
|
140 |
-}; |
|
141 |
- |
|
142 |
-JSONEditor.prototype.addUI = function(struct) { |
|
143 |
- var self = this; |
|
144 |
- return $('<a class="icon" href="#" title="add"><img src="' + this.ADD_IMG + '" border=0/></a>').click(function(e) { |
|
145 |
- if (struct instanceof Array) { |
|
146 |
- struct.push('??'); |
|
147 |
- } else { |
|
148 |
- struct['??'] = '??'; |
|
149 |
- } |
|
150 |
- self.doAutoFocus = true; |
|
151 |
- self.rebuild(); |
|
152 |
- return false; |
|
153 |
- }); |
|
154 |
-}; |
|
155 |
- |
|
156 |
-JSONEditor.prototype.undo = function() { |
|
157 |
- if (this.saveStateIfTextChanged()) { |
|
158 |
- if (this.historyPointer > 0) this.historyPointer -= 1; |
|
159 |
- this.restore(); |
|
160 |
- } |
|
161 |
-}; |
|
162 |
- |
|
163 |
-JSONEditor.prototype.redo = function() { |
|
164 |
- if (this.historyPointer + 1 < this.history.length) { |
|
165 |
- if (this.saveStateIfTextChanged()) { |
|
166 |
- this.historyPointer += 1; |
|
167 |
- this.restore(); |
|
168 |
- } |
|
169 |
- } |
|
170 |
-}; |
|
171 |
- |
|
172 |
-JSONEditor.prototype.showBuilder = function() { |
|
173 |
- if (this.checkJsonInText()) { |
|
174 |
- this.setJsonFromText(); |
|
175 |
- this.rebuild(); |
|
176 |
- this.wrapped.hide(); |
|
177 |
- this.builder.show(); |
|
178 |
- return true; |
|
179 |
- } else { |
|
180 |
- alert("Sorry, there appears to be an error in your JSON input. Please fix it before continuing."); |
|
181 |
- return false; |
|
182 |
- } |
|
183 |
-}; |
|
184 |
- |
|
185 |
-JSONEditor.prototype.showText = function() { |
|
186 |
- this.builder.hide(); |
|
187 |
- this.wrapped.show(); |
|
188 |
-}; |
|
189 |
- |
|
190 |
-JSONEditor.prototype.toggleBuilder = function() { |
|
191 |
- if(this.builderShowing){ |
|
192 |
- this.showText(); |
|
193 |
- this.builderShowing = !this.builderShowing; |
|
194 |
- } else { |
|
195 |
- if (this.showBuilder()) { |
|
196 |
- this.builderShowing = !this.builderShowing; |
|
181 |
+ }; |
|
182 |
+ |
|
183 |
+ JSONEditor.prototype.showText = function() { |
|
184 |
+ this.builder.hide(); |
|
185 |
+ return this.wrapped.show(); |
|
186 |
+ }; |
|
187 |
+ |
|
188 |
+ JSONEditor.prototype.toggleBuilder = function() { |
|
189 |
+ if (this.builderShowing) { |
|
190 |
+ this.showText(); |
|
191 |
+ return this.builderShowing = !this.builderShowing; |
|
192 |
+ } else { |
|
193 |
+ if (this.showBuilder()) { |
|
194 |
+ return this.builderShowing = !this.builderShowing; |
|
195 |
+ } |
|
197 | 196 |
} |
198 |
- } |
|
199 |
-}; |
|
200 |
- |
|
201 |
-JSONEditor.prototype.showFunctionButtons = function(insider) { |
|
202 |
- if (!insider) this.functionButtonsEnabled = true; |
|
203 |
- if (this.functionButtonsEnabled) if (!this.functionButtons) { |
|
204 |
- this.functionButtons = $('<div class="function_buttons"></div>'); |
|
205 |
- var self = this; |
|
206 |
- this.functionButtons.append($('<a href="#" style="padding-right: 10px;"></a>').click(function() { |
|
207 |
- self.undo(); |
|
208 |
- return false; |
|
209 |
- }).text('Undo')).append($('<a href="#" style="padding-right: 10px;"></a>').click(function() { |
|
210 |
- self.redo(); |
|
211 |
- return false; |
|
212 |
- }).text('Redo')).append($('<a id="toggle_view" href="#" style="padding-right: 10px;"></a>').click(function() { |
|
213 |
- self.toggleBuilder(); |
|
214 |
- return false; |
|
215 |
- }).text('Toggle View')); |
|
216 |
- this.container.prepend(this.functionButtons); |
|
217 |
- this.container.height(this.container.height() + this.functionButtons.height() + 5); |
|
218 |
- } |
|
219 |
- if (this.functionButtons) { |
|
220 |
- this.wrapped.css('top', this.functionButtons.height() + 5 + 'px'); |
|
221 |
- this.builder.css('top', this.functionButtons.height() + 5 + 'px'); |
|
222 |
- } |
|
223 |
-}; |
|
224 |
- |
|
225 |
-JSONEditor.prototype.saveStateIfTextChanged = function() { |
|
226 |
- if (JSON.stringify(this.json, null, 2) != this.wrapped.get(0).value) { |
|
227 |
- if (this.checkJsonInText()) { |
|
228 |
- this.saveState(true); |
|
229 |
- } else { |
|
230 |
- if (confirm("The current JSON is malformed. If you continue, the current JSON will not be saved. Do you wish to continue?")) { |
|
231 |
- this.historyPointer += 1; |
|
197 |
+ }; |
|
198 |
+ |
|
199 |
+ JSONEditor.prototype.showFunctionButtons = function(insider) { |
|
200 |
+ var _this = this; |
|
201 |
+ if (!insider) { |
|
202 |
+ this.functionButtonsEnabled = true; |
|
203 |
+ } |
|
204 |
+ if (this.functionButtonsEnabled && !this.functionButtons) { |
|
205 |
+ this.functionButtons = $('<div class="function_buttons"></div>'); |
|
206 |
+ this.functionButtons.append($('<a href="#" style="padding-right: 10px;">Undo</a>').click(function(e) { |
|
207 |
+ e.preventDefault(); |
|
208 |
+ return _this.undo(); |
|
209 |
+ })); |
|
210 |
+ this.functionButtons.append($('<a href="#" style="padding-right: 10px;">Redo</a>').click(function(e) { |
|
211 |
+ e.preventDefault(); |
|
212 |
+ return _this.redo(); |
|
213 |
+ })); |
|
214 |
+ this.functionButtons.append($('<a id="toggle_view" href="#" style="padding-right: 10px; float: right;">Toggle View</a>').click(function(e) { |
|
215 |
+ e.preventDefault(); |
|
216 |
+ return _this.toggleBuilder(); |
|
217 |
+ })); |
|
218 |
+ return this.container.prepend(this.functionButtons); |
|
219 |
+ } |
|
220 |
+ }; |
|
221 |
+ |
|
222 |
+ JSONEditor.prototype.saveStateIfTextChanged = function() { |
|
223 |
+ if (JSON.stringify(this.json, null, 2) !== this.wrapped.get(0).value) { |
|
224 |
+ if (this.checkJsonInText()) { |
|
225 |
+ this.saveState(true); |
|
226 |
+ } else { |
|
227 |
+ if (confirm("The current JSON is malformed. If you continue, the current JSON will not be saved. Do you wish to continue?")) { |
|
228 |
+ this.historyPointer += 1; |
|
229 |
+ true; |
|
230 |
+ } else { |
|
231 |
+ false; |
|
232 |
+ } |
|
233 |
+ } |
|
234 |
+ } |
|
235 |
+ return true; |
|
236 |
+ }; |
|
237 |
+ |
|
238 |
+ JSONEditor.prototype.restore = function() { |
|
239 |
+ if (this.history[this.historyPointer]) { |
|
240 |
+ this.wrapped.get(0).value = this.history[this.historyPointer]; |
|
241 |
+ return this.rebuild(true); |
|
242 |
+ } |
|
243 |
+ }; |
|
244 |
+ |
|
245 |
+ JSONEditor.prototype.saveState = function(skipStoreText) { |
|
246 |
+ var text; |
|
247 |
+ if (this.json) { |
|
248 |
+ if (!skipStoreText) { |
|
249 |
+ this.storeToText(); |
|
250 |
+ } |
|
251 |
+ text = this.wrapped.get(0).value; |
|
252 |
+ if (this.history[this.historyPointer] !== text) { |
|
253 |
+ this.historyTruncate(); |
|
254 |
+ this.history.push(text); |
|
255 |
+ return this.historyPointer += 1; |
|
256 |
+ } |
|
257 |
+ } |
|
258 |
+ }; |
|
259 |
+ |
|
260 |
+ JSONEditor.prototype.fireChange = function() { |
|
261 |
+ return $(this.wrapped).trigger('change'); |
|
262 |
+ }; |
|
263 |
+ |
|
264 |
+ JSONEditor.prototype.historyTruncate = function() { |
|
265 |
+ if (this.historyPointer + 1 < this.history.length) { |
|
266 |
+ return this.history.splice(this.historyPointer + 1, this.history.length - this.historyPointer); |
|
267 |
+ } |
|
268 |
+ }; |
|
269 |
+ |
|
270 |
+ JSONEditor.prototype.storeToText = function() { |
|
271 |
+ return this.wrapped.get(0).value = JSON.stringify(this.json, null, 2); |
|
272 |
+ }; |
|
273 |
+ |
|
274 |
+ JSONEditor.prototype.getJSONText = function() { |
|
275 |
+ this.rebuild(); |
|
276 |
+ return this.wrapped.get(0).value; |
|
277 |
+ }; |
|
278 |
+ |
|
279 |
+ JSONEditor.prototype.getJSON = function() { |
|
280 |
+ this.rebuild(); |
|
281 |
+ return this.json; |
|
282 |
+ }; |
|
283 |
+ |
|
284 |
+ JSONEditor.prototype.rebuild = function(doNotRefreshText) { |
|
285 |
+ var changed, elem; |
|
286 |
+ if (!this.json) { |
|
287 |
+ this.setJsonFromText(); |
|
288 |
+ } |
|
289 |
+ changed = this.haveThingsChanged(); |
|
290 |
+ if (this.json && !doNotRefreshText) { |
|
291 |
+ this.saveState(); |
|
292 |
+ } |
|
293 |
+ this.cleanBuilder(); |
|
294 |
+ this.setJsonFromText(); |
|
295 |
+ this.alreadyFocused = false; |
|
296 |
+ elem = this.build(this.json, this.builder, null, null, this.json); |
|
297 |
+ this.recoverScrollPosition(); |
|
298 |
+ if (elem && elem.text() === '??' && !this.alreadyFocused && this.doAutoFocus) { |
|
299 |
+ this.alreadyFocused = true; |
|
300 |
+ this.doAutoFocus = false; |
|
301 |
+ elem = elem.find('.editable'); |
|
302 |
+ elem.click(); |
|
303 |
+ elem.find('input').focus().select(); |
|
304 |
+ } |
|
305 |
+ if (changed) { |
|
306 |
+ return this.fireChange(); |
|
307 |
+ } |
|
308 |
+ }; |
|
309 |
+ |
|
310 |
+ JSONEditor.prototype.haveThingsChanged = function() { |
|
311 |
+ return this.json && JSON.stringify(this.json, null, 2) !== this.wrapped.get(0).value; |
|
312 |
+ }; |
|
313 |
+ |
|
314 |
+ JSONEditor.prototype.saveScrollPosition = function() { |
|
315 |
+ return this.oldScrollHeight = this.builder.scrollTop(); |
|
316 |
+ }; |
|
317 |
+ |
|
318 |
+ JSONEditor.prototype.recoverScrollPosition = function() { |
|
319 |
+ return this.builder.scrollTop(this.oldScrollHeight); |
|
320 |
+ }; |
|
321 |
+ |
|
322 |
+ JSONEditor.prototype.setJsonFromText = function() { |
|
323 |
+ if (this.wrapped.get(0).value.length === 0) { |
|
324 |
+ this.wrapped.get(0).value = "{}"; |
|
325 |
+ } |
|
326 |
+ try { |
|
327 |
+ this.wrapped.get(0).value = this.wrapped.get(0).value.replace(/((^|[^\\])(\\\\)*)\\n/g, '$1\\\\n').replace(/((^|[^\\])(\\\\)*)\\t/g, '$1\\\\t'); |
|
328 |
+ return this.json = JSON.parse(this.wrapped.get(0).value); |
|
329 |
+ } catch (e) { |
|
330 |
+ return alert("Got bad JSON from text."); |
|
331 |
+ } |
|
332 |
+ }; |
|
333 |
+ |
|
334 |
+ JSONEditor.prototype.checkJsonInText = function() { |
|
335 |
+ try { |
|
336 |
+ JSON.parse(this.wrapped.get(0).value); |
|
232 | 337 |
return true; |
233 |
- } else { |
|
338 |
+ } catch (e) { |
|
234 | 339 |
return false; |
235 | 340 |
} |
236 |
- } |
|
237 |
- } |
|
238 |
- return true; |
|
239 |
-}; |
|
240 |
- |
|
241 |
-JSONEditor.prototype.restore = function() { |
|
242 |
- if (this.history[this.historyPointer]) { |
|
243 |
- this.wrapped.get(0).value = this.history[this.historyPointer]; |
|
244 |
- this.rebuild(true); |
|
245 |
- } |
|
246 |
-}; |
|
247 |
- |
|
248 |
-JSONEditor.prototype.saveState = function(skipStoreText) { |
|
249 |
- if (this.json) { |
|
250 |
- if (!skipStoreText) this.storeToText(); |
|
251 |
- var text = this.wrapped.get(0).value; |
|
252 |
- if (this.history[this.historyPointer] != text) { |
|
253 |
- this.historyTruncate(); |
|
254 |
- this.history.push(text); |
|
255 |
- this.historyPointer += 1; |
|
256 |
- } |
|
257 |
- } |
|
258 |
-}; |
|
259 |
- |
|
260 |
-JSONEditor.prototype.fireChange = function() { |
|
261 |
- $(this.wrapped).trigger('change'); |
|
262 |
-}; |
|
263 |
- |
|
264 |
-JSONEditor.prototype.historyTruncate = function() { |
|
265 |
- if (this.historyPointer + 1 < this.history.length) { |
|
266 |
- this.history.splice(this.historyPointer + 1, this.history.length - this.historyPointer); |
|
267 |
- } |
|
268 |
-}; |
|
269 |
- |
|
270 |
-JSONEditor.prototype.storeToText = function() { |
|
271 |
- this.wrapped.get(0).value = JSON.stringify(this.json, null, 2); |
|
272 |
-}; |
|
273 |
- |
|
274 |
-JSONEditor.prototype.getJSONText = function() { |
|
275 |
- this.rebuild(); |
|
276 |
- return this.wrapped.get(0).value; |
|
277 |
-}; |
|
278 |
- |
|
279 |
-JSONEditor.prototype.getJSON = function() { |
|
280 |
- this.rebuild(); |
|
281 |
- return this.json; |
|
282 |
-}; |
|
283 |
- |
|
284 |
-JSONEditor.prototype.rebuild = function(doNotRefreshText) { |
|
285 |
- if (!this.json) this.setJsonFromText(); |
|
286 |
- var changed = this.haveThingsChanged(); |
|
287 |
- if (this.json && !doNotRefreshText) { |
|
288 |
- this.saveState(); |
|
289 |
- } |
|
290 |
- this.cleanBuilder(); |
|
291 |
- this.setJsonFromText(); |
|
292 |
- this.alreadyFocused = false; |
|
293 |
- var elem = this.build(this.json, this.builder, null, null, this.json); |
|
294 |
- |
|
295 |
- this.recoverScrollPosition(); |
|
296 |
- |
|
297 |
- // Auto-focus to edit '??' keys and values. |
|
298 |
- if (elem) if (elem.text() == '??' && !this.alreadyFocused && this.doAutoFocus) { |
|
299 |
- this.alreadyFocused = true; |
|
300 |
- this.doAutoFocus = false; |
|
301 |
- |
|
302 |
- elem = elem.find('.editable'); |
|
303 |
- elem.click(); |
|
304 |
- elem.find('input').focus().select(); |
|
305 |
- //still missing a proper scrolling into the selected input |
|
306 |
- } |
|
307 |
- |
|
308 |
- if (changed) this.fireChange(); |
|
309 |
-}; |
|
310 |
- |
|
311 |
-JSONEditor.prototype.haveThingsChanged = function() { |
|
312 |
- return (this.json && JSON.stringify(this.json, null, 2) != this.wrapped.get(0).value); |
|
313 |
-} |
|
314 |
- |
|
315 |
-JSONEditor.prototype.saveScrollPosition = function() { |
|
316 |
- this.oldScrollHeight = this.builder.scrollTop(); |
|
317 |
-}; |
|
318 |
- |
|
319 |
-JSONEditor.prototype.recoverScrollPosition = function() { |
|
320 |
- this.builder.scrollTop(this.oldScrollHeight); |
|
321 |
-}; |
|
322 |
- |
|
323 |
-JSONEditor.prototype.setJsonFromText = function() { |
|
324 |
- if (this.wrapped.get(0).value.length == 0) this.wrapped.get(0).value = "{}"; |
|
325 |
- try { |
|
326 |
- this.wrapped.get(0).value = this.wrapped.get(0).value.replace(/((^|[^\\])(\\\\)*)\\n/g, '$1\\\\n').replace(/((^|[^\\])(\\\\)*)\\t/g, '$1\\\\t'); |
|
327 |
- this.json = JSON.parse(this.wrapped.get(0).value); |
|
328 |
- } catch(e) { |
|
329 |
- alert("Got bad JSON from text."); |
|
330 |
- } |
|
331 |
-}; |
|
332 |
- |
|
333 |
-JSONEditor.prototype.checkJsonInText = function() { |
|
334 |
- try { |
|
335 |
- JSON.parse(this.wrapped.get(0).value); |
|
336 |
- return true; |
|
337 |
- } catch(e) { |
|
338 |
- return false; |
|
339 |
- } |
|
340 |
-}; |
|
341 |
- |
|
342 |
-JSONEditor.prototype.logJSON = function() { |
|
343 |
- console.log(JSON.stringify(this.json, null, 2)); |
|
344 |
-}; |
|
345 |
- |
|
346 |
-JSONEditor.prototype.cleanBuilder = function() { |
|
347 |
- if (!this.builder) { |
|
348 |
- this.builder = $('<div class="builder"></div>'); |
|
349 |
- this.container.append(this.builder); |
|
350 |
- } |
|
351 |
- this.saveScrollPosition(); |
|
352 |
- this.builder.text(''); |
|
353 |
- |
|
354 |
- this.builder.css("position", "absolute").css("top", 0).css("left", 0); |
|
355 |
- this.builder.width(this.wrapped.width()).height(this.wrapped.height()); |
|
356 |
- this.wrapped.css("position", "absolute").css("top", 0).css("left", 0); |
|
357 |
- this.showFunctionButtons("defined"); |
|
358 |
-}; |
|
359 |
- |
|
360 |
-JSONEditor.prototype.updateStruct = function(struct, key, val, kind, selectionStart, selectionEnd) { |
|
361 |
- if(kind == 'key') { |
|
362 |
- if (selectionStart && selectionEnd) val = key.substring(0, selectionStart) + val + key.substring(selectionEnd, key.length); |
|
363 |
- struct[val] = struct[key]; |
|
364 |
- |
|
365 |
- //order keys |
|
366 |
- var orderrest = 0; |
|
367 |
- $.each(struct, function (index, value) { |
|
368 |
- //re set rest of the keys |
|
369 |
- if(orderrest & index != val) { |
|
370 |
- var tempval = struct[index]; |
|
371 |
- delete struct[index]; |
|
372 |
- struct[index] = tempval; |
|
373 |
- } |
|
374 |
- if(key == index) { |
|
375 |
- orderrest = 1; |
|
376 |
- } |
|
377 |
- }); |
|
378 |
- // end of order keys |
|
379 |
- |
|
380 |
- if (key != val) delete struct[key]; |
|
381 |
- } else { |
|
382 |
- if (selectionStart && selectionEnd) val = struct[key].substring(0, selectionStart) + val + struct[key].substring(selectionEnd, struct[key].length); |
|
383 |
- struct[key] = val; |
|
384 |
- } |
|
385 |
-}; |
|
386 |
- |
|
387 |
-JSONEditor.prototype.getValFromStruct = function(struct, key, kind) { |
|
388 |
- if(kind == 'key') { |
|
389 |
- return key; |
|
390 |
- } else { |
|
391 |
- return struct[key]; |
|
392 |
- } |
|
393 |
-}; |
|
394 |
- |
|
395 |
-JSONEditor.prototype.doTruncation = function(trueOrFalse) { |
|
396 |
- if (this._doTruncation != trueOrFalse) { |
|
397 |
- this._doTruncation = trueOrFalse; |
|
398 |
- this.rebuild(); |
|
399 |
- } |
|
400 |
-}; |
|
401 |
- |
|
402 |
-JSONEditor.prototype.showWipe = function(trueOrFalse) { |
|
403 |
- if (this._showWipe != trueOrFalse) { |
|
404 |
- this._showWipe = trueOrFalse; |
|
405 |
- this.rebuild(); |
|
406 |
- } |
|
407 |
-}; |
|
408 |
- |
|
409 |
-JSONEditor.prototype.truncate = function(text, length) { |
|
410 |
- if (text.length == 0) return '-empty-'; |
|
411 |
- if(this._doTruncation && text.length > (length || 30)) return(text.substring(0, (length || 30)) + '...'); |
|
412 |
- return text; |
|
413 |
-}; |
|
414 |
- |
|
415 |
-JSONEditor.prototype.replaceLastSelectedFieldIfRecent = function(text) { |
|
416 |
- if (this.lastEditingUnfocusedTime > (new Date()).getTime() - 200) { // Short delay for unfocus to occur. |
|
417 |
- this.setLastEditingFocus(text); |
|
418 |
- this.rebuild(); |
|
419 |
- } |
|
420 |
-}; |
|
421 |
- |
|
422 |
-JSONEditor.prototype.editingUnfocused = function(elem, struct, key, root, kind) { |
|
423 |
- var self = this; |
|
424 |
- |
|
425 |
- var selectionStart = elem && elem.target.selectionStart; |
|
426 |
- var selectionEnd = elem && elem.target.selectionEnd; |
|
427 |
- |
|
428 |
- this.setLastEditingFocus = function(text) { |
|
429 |
- self.updateStruct(struct, key, text, kind, selectionStart, selectionEnd); |
|
430 |
- self.json = root; // Because self.json is a new reference due to rebuild. |
|
431 |
- }; |
|
432 |
- this.lastEditingUnfocusedTime = (new Date()).getTime(); |
|
433 |
-}; |
|
434 |
- |
|
435 |
-JSONEditor.prototype.edit = function(e, key, struct, root, kind){ |
|
436 |
- var self = this; |
|
437 |
- var form = $("<form></form>").css('display', 'inline'); |
|
438 |
- var input = document.createElement("INPUT"); |
|
439 |
- input.value = this.getValFromStruct(struct, key, kind); |
|
440 |
- //alert(this.getValFromStruct(struct, key, kind)); |
|
441 |
- input.className = 'edit_field'; |
|
442 |
- var onblur = function(elem) { |
|
443 |
- var val = input.value; |
|
444 |
- self.updateStruct(struct, key, val, kind); |
|
445 |
- self.editingUnfocused(elem, struct, (kind == 'key' ? val : key), root, kind); |
|
446 |
- e.text(self.truncate(val)); |
|
447 |
- e.get(0).editing = false; |
|
448 |
- if (key != val) self.rebuild(); |
|
449 |
- return false; |
|
450 |
- }; |
|
451 |
- $(input).blur(onblur); |
|
452 |
- $(input).keydown(function(e) { |
|
453 |
- if (e.keyCode == 9 || e.keyCode == 13) { // Tab and enter |
|
454 |
- self.doAutoFocus = true; |
|
455 |
- onblur(e); |
|
456 |
- return false; |
|
457 |
- } |
|
458 |
- }); |
|
459 |
- $(form).submit(function(e) { self.doAutoFocus = true; onblur(e); return false;}).append(input); |
|
460 |
- $(e).html(form); |
|
461 |
- input.focus(); |
|
462 |
-}; |
|
463 |
- |
|
464 |
-JSONEditor.prototype.editable = function(text, key, struct, root, kind) { |
|
465 |
- var self = this; |
|
466 |
- var elem = $('<span class="editable" href="#"></span>').text(this.truncate(text)).click(function(e) { |
|
467 |
- if (!this.editing) { |
|
468 |
- this.editing = true; |
|
469 |
- self.edit($(this), key, struct, root, kind); |
|
470 |
- } |
|
471 |
- return true; |
|
472 |
- }); |
|
473 |
- |
|
474 |
- return elem; |
|
475 |
-} |
|
476 |
- |
|
477 |
-JSONEditor.prototype.build = function(json, node, parent, key, root) { |
|
478 |
- var elem = null; |
|
479 |
- if(json instanceof Array){ |
|
480 |
- var bq = $(document.createElement("BLOCKQUOTE")); |
|
481 |
- bq.append($('<div class="brackets">[</div>')); |
|
482 |
- |
|
483 |
- bq.prepend(this.addUI(json)); |
|
484 |
- if (parent) { |
|
485 |
- if (this._showWipe) bq.prepend(this.wipeUI(key, parent)); |
|
486 |
- bq.prepend(this.deleteUI(key, parent)); |
|
487 |
- } |
|
341 |
+ }; |
|
488 | 342 |
|
489 |
- for(var i = 0; i < json.length; i++) { |
|
490 |
- var innerbq = $(document.createElement("BLOCKQUOTE")); |
|
491 |
- var newElem = this.build(json[i], innerbq, json, i, root); |
|
492 |
- if (newElem) if (newElem.text() == "??") elem = newElem; |
|
493 |
- bq.append(innerbq); |
|
494 |
- } |
|
343 |
+ JSONEditor.prototype.logJSON = function() { |
|
344 |
+ return console.log(JSON.stringify(this.json, null, 2)); |
|
345 |
+ }; |
|
495 | 346 |
|
496 |
- bq.append($('<div class="brackets">]</div>')); |
|
497 |
- node.append(bq); |
|
498 |
- } else if (json instanceof Object) { |
|
499 |
- var bq = $(document.createElement("BLOCKQUOTE")); |
|
500 |
- bq.append($('<div class="bracers">{</div>')); |
|
501 |
- |
|
502 |
- for(var i in json){ |
|
503 |
- var innerbq = $(document.createElement("BLOCKQUOTE")); |
|
504 |
- var newElem = this.editable(i.toString(), i.toString(), json, root, 'key').wrap('<span class="key"></span>').parent(); |
|
505 |
- innerbq.append(newElem); |
|
506 |
- if (newElem) if (newElem.text() == "??") elem = newElem; |
|
507 |
- if (typeof json[i] != 'string' && typeof json[i] != 'number') { |
|
508 |
- innerbq.prepend(this.braceUI(i, json)); |
|
509 |
- innerbq.prepend(this.bracketUI(i, json)); |
|
510 |
- if (this._showWipe) innerbq.prepend(this.wipeUI(i, json)); |
|
511 |
- innerbq.prepend(this.deleteUI(i, json, true)); |
|
347 |
+ JSONEditor.prototype.cleanBuilder = function() { |
|
348 |
+ if (!this.builder) { |
|
349 |
+ this.builder = $('<div class="builder"></div>'); |
|
350 |
+ this.container.append(this.builder); |
|
512 | 351 |
} |
513 |
- innerbq.append($('<span class="colon">: </span>')); |
|
514 |
- newElem = this.build(json[i], innerbq, json, i, root); |
|
515 |
- if (newElem) if (newElem.text() == "??") elem = newElem; |
|
516 |
- bq.append(innerbq); |
|
517 |
- } |
|
352 |
+ this.saveScrollPosition(); |
|
353 |
+ this.builder.text(''); |
|
354 |
+ return this.showFunctionButtons("defined"); |
|
355 |
+ }; |
|
356 |
+ |
|
357 |
+ JSONEditor.prototype.updateStruct = function(struct, key, val, kind, selectionStart, selectionEnd) { |
|
358 |
+ var orderrest; |
|
359 |
+ if (kind === 'key') { |
|
360 |
+ if (selectionStart && selectionEnd) { |
|
361 |
+ val = key.substring(0, selectionStart) + val + key.substring(selectionEnd, key.length); |
|
362 |
+ } |
|
363 |
+ struct[val] = struct[key]; |
|
364 |
+ orderrest = 0; |
|
365 |
+ $.each(struct, function(index, value) { |
|
366 |
+ var tempval; |
|
367 |
+ if (orderrest & index !== val) { |
|
368 |
+ tempval = struct[index]; |
|
369 |
+ delete struct[index]; |
|
370 |
+ struct[index] = tempval; |
|
371 |
+ } |
|
372 |
+ if (key === index) { |
|
373 |
+ return orderrest = 1; |
|
374 |
+ } |
|
375 |
+ }); |
|
376 |
+ if (key !== val) { |
|
377 |
+ return delete struct[key]; |
|
378 |
+ } |
|
379 |
+ } else { |
|
380 |
+ if (selectionStart && selectionEnd) { |
|
381 |
+ val = struct[key].substring(0, selectionStart) + val + struct[key].substring(selectionEnd, struct[key].length); |
|
382 |
+ } |
|
383 |
+ return struct[key] = val; |
|
384 |
+ } |
|
385 |
+ }; |
|
518 | 386 |
|
519 |
- bq.prepend(this.addUI(json)); |
|
520 |
- if (parent) { |
|
521 |
- if (this._showWipe) bq.prepend(this.wipeUI(key, parent)); |
|
522 |
- bq.prepend(this.deleteUI(key, parent)); |
|
523 |
- } |
|
387 |
+ JSONEditor.prototype.getValFromStruct = function(struct, key, kind) { |
|
388 |
+ if (kind === 'key') { |
|
389 |
+ return key; |
|
390 |
+ } else { |
|
391 |
+ return struct[key]; |
|
392 |
+ } |
|
393 |
+ }; |
|
524 | 394 |
|
525 |
- bq.append($('<div class="bracers">}</div>')); |
|
526 |
- node.append(bq); |
|
527 |
- } else { |
|
528 |
- elem = this.editable(json.toString(), key, parent, root, 'value').wrap('<span class="val"></span>').parent(); |
|
529 |
- node.append(elem); |
|
530 |
- node.prepend(this.braceUI(key, parent)); |
|
531 |
- node.prepend(this.bracketUI(key, parent)); |
|
532 |
- if (parent) { |
|
533 |
- if (this._showWipe) node.prepend(this.wipeUI(key, parent)); |
|
534 |
- node.prepend(this.deleteUI(key, parent)); |
|
535 |
- } |
|
395 |
+ JSONEditor.prototype.doTruncation = function(trueOrFalse) { |
|
396 |
+ if (this._doTruncation !== trueOrFalse) { |
|
397 |
+ this._doTruncation = trueOrFalse; |
|
398 |
+ return this.rebuild(); |
|
399 |
+ } |
|
400 |
+ }; |
|
401 |
+ |
|
402 |
+ JSONEditor.prototype.showWipe = function(trueOrFalse) { |
|
403 |
+ if (this._showWipe !== trueOrFalse) { |
|
404 |
+ this._showWipe = trueOrFalse; |
|
405 |
+ return this.rebuild(); |
|
406 |
+ } |
|
407 |
+ }; |
|
408 |
+ |
|
409 |
+ JSONEditor.prototype.truncate = function(text, length) { |
|
410 |
+ if (text.length === 0) { |
|
411 |
+ return '-empty-'; |
|
412 |
+ } |
|
413 |
+ if (this._doTruncation && text.length > (length || 30)) { |
|
414 |
+ return text.substring(0, length || 30) + '...'; |
|
415 |
+ } |
|
416 |
+ return text; |
|
417 |
+ }; |
|
418 |
+ |
|
419 |
+ JSONEditor.prototype.replaceLastSelectedFieldIfRecent = function(text) { |
|
420 |
+ if (this.lastEditingUnfocusedTime > (new Date()).getTime() - 200) { |
|
421 |
+ this.setLastEditingFocus(text); |
|
422 |
+ return this.rebuild(); |
|
423 |
+ } |
|
424 |
+ }; |
|
425 |
+ |
|
426 |
+ JSONEditor.prototype.editingUnfocused = function(elem, struct, key, root, kind) { |
|
427 |
+ var selectionEnd, selectionStart, |
|
428 |
+ _this = this; |
|
429 |
+ selectionStart = elem != null ? elem.selectionStart : void 0; |
|
430 |
+ selectionEnd = elem != null ? elem.selectionEnd : void 0; |
|
431 |
+ this.setLastEditingFocus = function(text) { |
|
432 |
+ _this.updateStruct(struct, key, text, kind, selectionStart, selectionEnd); |
|
433 |
+ return _this.json = root; |
|
434 |
+ }; |
|
435 |
+ return this.lastEditingUnfocusedTime = (new Date()).getTime(); |
|
436 |
+ }; |
|
437 |
+ |
|
438 |
+ JSONEditor.prototype.edit = function($elem, key, struct, root, kind) { |
|
439 |
+ var $input, blurHandler, form, |
|
440 |
+ _this = this; |
|
441 |
+ form = $("<form></form>").css('display', 'inline'); |
|
442 |
+ $input = $("<input />"); |
|
443 |
+ $input.val(this.getValFromStruct(struct, key, kind)); |
|
444 |
+ $input.addClass('edit_field'); |
|
445 |
+ blurHandler = function() { |
|
446 |
+ var val, _ref; |
|
447 |
+ val = $input.val(); |
|
448 |
+ _this.updateStruct(struct, key, val, kind); |
|
449 |
+ _this.editingUnfocused($elem, struct, (_ref = kind === 'key') != null ? _ref : { |
|
450 |
+ val: key |
|
451 |
+ }, root, kind); |
|
452 |
+ $elem.text(_this.truncate(val)); |
|
453 |
+ $elem.get(0).editing = false; |
|
454 |
+ if (key !== val) { |
|
455 |
+ return _this.rebuild(); |
|
456 |
+ } |
|
457 |
+ }; |
|
458 |
+ $input.blur(blurHandler); |
|
459 |
+ $input.keydown(function(e) { |
|
460 |
+ if (e.keyCode === 9 || e.keyCode === 13) { |
|
461 |
+ _this.doAutoFocus = true; |
|
462 |
+ return blurHandler(); |
|
463 |
+ } |
|
464 |
+ }); |
|
465 |
+ $(form).append($input).submit(function(e) { |
|
466 |
+ e.preventDefault(); |
|
467 |
+ _this.doAutoFocus = true; |
|
468 |
+ return blurHandler(); |
|
469 |
+ }); |
|
470 |
+ $elem.html(form); |
|
471 |
+ return $input.focus(); |
|
472 |
+ }; |
|
473 |
+ |
|
474 |
+ JSONEditor.prototype.editable = function(text, key, struct, root, kind) { |
|
475 |
+ var elem, self; |
|
476 |
+ self = this; |
|
477 |
+ elem = $('<span class="editable" href="#"></span>').text(this.truncate(text)).click(function(e) { |
|
478 |
+ if (!this.editing) { |
|
479 |
+ this.editing = true; |
|
480 |
+ self.edit($(this), key, struct, root, kind); |
|
481 |
+ } |
|
482 |
+ return true; |
|
483 |
+ }); |
|
484 |
+ return elem; |
|
485 |
+ }; |
|
486 |
+ |
|
487 |
+ JSONEditor.prototype.build = function(json, node, parent, key, root) { |
|
488 |
+ var bq, elem, i, innerbq, jsonkey, jsonvalue, newElem, _i, _ref; |
|
489 |
+ elem = null; |
|
490 |
+ if (json instanceof Array) { |
|
491 |
+ bq = $(document.createElement("BLOCKQUOTE")); |
|
492 |
+ bq.append($('<div class="brackets">[</div>')); |
|
493 |
+ bq.prepend(this.addUI(json)); |
|
494 |
+ if (parent) { |
|
495 |
+ if (this._showWipe) { |
|
496 |
+ bq.prepend(this.wipeUI(key, parent)); |
|
497 |
+ } |
|
498 |
+ bq.prepend(this.deleteUI(key, parent)); |
|
499 |
+ } |
|
500 |
+ for (i = _i = 0, _ref = json.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { |
|
501 |
+ innerbq = $(document.createElement("BLOCKQUOTE")); |
|
502 |
+ newElem = this.build(json[i], innerbq, json, i, root); |
|
503 |
+ if (newElem && newElem.text() === "??") { |
|
504 |
+ elem = newElem; |
|
505 |
+ } |
|
506 |
+ bq.append(innerbq); |
|
507 |
+ } |
|
508 |
+ bq.append($('<div class="brackets">]</div>')); |
|
509 |
+ node.append(bq); |
|
510 |
+ } else if (json instanceof Object) { |
|
511 |
+ bq = $(document.createElement("BLOCKQUOTE")); |
|
512 |
+ bq.append($('<div class="bracers">{</div>')); |
|
513 |
+ for (jsonkey in json) { |
|
514 |
+ jsonvalue = json[jsonkey]; |
|
515 |
+ innerbq = $(document.createElement("BLOCKQUOTE")); |
|
516 |
+ newElem = this.editable(jsonkey.toString(), jsonkey.toString(), json, root, 'key').wrap('<span class="key"></b>').parent(); |
|
517 |
+ innerbq.append(newElem); |
|
518 |
+ if (newElem && newElem.text() === "??") { |
|
519 |
+ elem = newElem; |
|
520 |
+ } |
|
521 |
+ if (typeof jsonvalue !== 'string') { |
|
522 |
+ innerbq.prepend(this.braceUI(jsonkey, json)); |
|
523 |
+ innerbq.prepend(this.bracketUI(jsonkey, json)); |
|
524 |
+ if (this._showWipe) { |
|
525 |
+ innerbq.prepend(this.wipeUI(jsonkey, json)); |
|
526 |
+ } |
|
527 |
+ innerbq.prepend(this.deleteUI(jsonkey, json, true)); |
|
528 |
+ } |
|
529 |
+ innerbq.append($('<span class="colon">: </span>')); |
|
530 |
+ newElem = this.build(jsonvalue, innerbq, json, jsonkey, root); |
|
531 |
+ if (newElem && newElem.text() === "??") { |
|
532 |
+ elem = newElem; |
|
533 |
+ } |
|
534 |
+ bq.append(innerbq); |
|
535 |
+ } |
|
536 |
+ bq.prepend(this.addUI(json)); |
|
537 |
+ if (parent) { |
|
538 |
+ if (this._showWipe) { |
|
539 |
+ bq.prepend(this.wipeUI(key, parent)); |
|
540 |
+ } |
|
541 |
+ bq.prepend(this.deleteUI(key, parent)); |
|
542 |
+ } |
|
543 |
+ bq.append($('<div class="bracers">}</div>')); |
|
544 |
+ node.append(bq); |
|
545 |
+ } else { |
|
546 |
+ elem = this.editable(json.toString(), key, parent, root, 'value').wrap('<span class="val"></span>').parent(); |
|
547 |
+ node.append(elem); |
|
548 |
+ node.prepend(this.braceUI(key, parent)); |
|
549 |
+ node.prepend(this.bracketUI(key, parent)); |
|
550 |
+ if (parent) { |
|
551 |
+ if (this._showWipe) { |
|
552 |
+ node.prepend(this.wipeUI(key, parent)); |
|
553 |
+ } |
|
554 |
+ node.prepend(this.deleteUI(key, parent)); |
|
555 |
+ } |
|
556 |
+ } |
|
557 |
+ return elem; |
|
558 |
+ }; |
|
559 |
+ |
|
560 |
+ return JSONEditor; |
|
561 |
+ |
|
562 |
+ })(); |
|
536 | 563 |
|
537 |
- } |
|
538 |
- return elem; |
|
539 |
-}; |
|
564 |
+}).call(this); |
@@ -0,0 +1,37 @@ |
||
1 |
+.json-editor { |
|
2 |
+ background-color: #FFF; |
|
3 |
+ position: relative; } |
|
4 |
+ .json-editor textarea { |
|
5 |
+ width: 100%; |
|
6 |
+ font-family: monospace; } |
|
7 |
+ .json-editor .builder { |
|
8 |
+ background-color: white; |
|
9 |
+ overflow: auto; |
|
10 |
+ font-size: 0.9em; } |
|
11 |
+ .json-editor .builder .key { |
|
12 |
+ font-weight: bold; } |
|
13 |
+ .json-editor .builder .key .edit_field { |
|
14 |
+ width: 150px; } |
|
15 |
+ .json-editor .builder .val .edit_field { |
|
16 |
+ width: 200px; } |
|
17 |
+ .json-editor blockquote { |
|
18 |
+ margin: 0; |
|
19 |
+ padding: 0; |
|
20 |
+ clear: both; |
|
21 |
+ padding-left: 7px; } |
|
22 |
+ .json-editor div { |
|
23 |
+ background-color: #cfc; |
|
24 |
+ margin: 1px; |
|
25 |
+ padding: 2px; } |
|
26 |
+ .json-editor .val { |
|
27 |
+ font-style: italic; } |
|
28 |
+ .json-editor .key a, .json-editor .val a { |
|
29 |
+ color: black; |
|
30 |
+ text-decoration: none; } |
|
31 |
+ .json-editor .icon { |
|
32 |
+ display: block; |
|
33 |
+ float: right; |
|
34 |
+ text-decoration: none; |
|
35 |
+ padding-left: 5px; |
|
36 |
+ border: 0; |
|
37 |
+ color: blue; } |
@@ -1,63 +0,0 @@ |
||
1 |
-.json-editor { |
|
2 |
- background-color: #FFF; |
|
3 |
- position: relative; |
|
4 |
- |
|
5 |
- .builder { |
|
6 |
- background-color: white; |
|
7 |
- overflow: auto; |
|
8 |
- font-size: 0.9em; |
|
9 |
- padding-right: 10px; |
|
10 |
- |
|
11 |
- .key { |
|
12 |
- font-weight: bold; |
|
13 |
- |
|
14 |
- .edit_field { |
|
15 |
- width: 80px; |
|
16 |
- } |
|
17 |
- |
|
18 |
- a { |
|
19 |
- color: black; |
|
20 |
- text-decoration: none; |
|
21 |
- } |
|
22 |
- } |
|
23 |
- |
|
24 |
- .val { |
|
25 |
- font-style: italic; |
|
26 |
- |
|
27 |
- .edit_field { |
|
28 |
- width: 180px; |
|
29 |
- } |
|
30 |
- |
|
31 |
- a { |
|
32 |
- color: black; |
|
33 |
- text-decoration: none; |
|
34 |
- } |
|
35 |
- } |
|
36 |
- } |
|
37 |
- |
|
38 |
- blockquote { |
|
39 |
- margin: 0; |
|
40 |
- padding: 0; |
|
41 |
- clear: both; |
|
42 |
- padding-left: 7px; |
|
43 |
- } |
|
44 |
- |
|
45 |
- div { |
|
46 |
- background-color: #cfc; |
|
47 |
- margin: 1px; |
|
48 |
- padding: 2px; |
|
49 |
- } |
|
50 |
- |
|
51 |
- .icon { |
|
52 |
- display: block; |
|
53 |
- float: right; |
|
54 |
- text-decoration: none; |
|
55 |
- padding: 0 5px; |
|
56 |
- border: 0 !important; |
|
57 |
- color: blue; |
|
58 |
- |
|
59 |
- &:hover { |
|
60 |
- background-color: #bbb; |
|
61 |
- } |
|
62 |
- } |
|
63 |
-} |