Nicer formatting of JSONEditor; minor tweeks; Scenarios show up in the quick navigation menu

Andrew Cantino лет %!s(int64=10): %!d(string=назад)
Родитель
Сommit
a7ed5b5307

+ 13 - 0
app/assets/stylesheets/scenarios.css.scss

@@ -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
 }

+ 6 - 7
app/models/agents/pushover_agent.rb

@@ -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

+ 2 - 2
app/views/agents/_form.html.erb

@@ -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
       

+ 14 - 10
app/views/layouts/application.html.erb

@@ -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>

+ 3 - 4
app/views/scenario_imports/_step_one.html.erb

@@ -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'>

+ 6 - 4
app/views/scenario_imports/_step_two.html.erb

@@ -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>

+ 2 - 1
app/views/scenarios/index.html.erb

@@ -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>

+ 1 - 1
app/views/scenarios/show.html.erb

@@ -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? %>

+ 514 - 489
vendor/assets/javascripts/jquery.json-editor.js

@@ -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);

+ 37 - 0
vendor/assets/stylesheets/jquery.json-editor.css

@@ -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; }

+ 0 - 63
vendor/assets/stylesheets/jquery.json-editor.css.scss

@@ -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
-}