Shortcake (Shortcode UI) - Version 0.5.0

Version Description

(August 26, 2015) = * Attachment field: Made it easier to change the attachment by clicking on the thumbnail; added attachment metadata in the field view. * Attachment field: Refactored JavaScript to trigger events. * Added a range input type. * Introduced a register_shortcode_ui hook for plugins to more safely register UI with. * Removed Preview tab to bring Shortcake's user experience closer to Core, in which the inline visual preview is preferred over a separate preview in the media modal. * Cleaned up JavaScript using JSHint. * Added Russian translation. * Added Portuguese translation. * Added PHPDoc to all classes. * Bug fix: Persists inner_content for a shortcode even when UI isn't defined. * Bug fix: Hitting esc in a Shortcake view will now close the modal. (Fixed in Core.) * Bug fix: Hitting delete when a Shortcake preview is selected in the Visual editor now results in the shortcode being removed. (Fixed in Core.) * Bug fix: The Shortcake 'search' function no longer visually conflicts with the shortcode grid at small screen sizes. (Fixed in Core.) * Bug fix: Use get_post_type() instead of get_current_screen()->post_type so context is properly set on the frontend. * Full release notes

Download this release

Release Info

Developer danielbachhuber
Plugin Icon 128x128 Shortcake (Shortcode UI)
Version 0.5.0
Comparing to
See all releases

Code changes from version 0.4.0 to 0.5.0

Files changed (42) hide show
  1. .jshintrc +25 -0
  2. Gruntfile.js +7 -5
  3. css/sass/_field-image.scss +13 -0
  4. css/sass/shortcode-ui.scss +16 -2
  5. css/shortcode-ui.css +17 -0
  6. css/shortcode-ui.css.map +1 -1
  7. inc/class-shortcode-ui.php +134 -25
  8. inc/fields/class-field-attachment.php +52 -9
  9. inc/fields/class-field-color.php +42 -18
  10. inc/fields/class-field-post-select.php +1 -7
  11. inc/fields/class-shortcode-ui-fields.php +38 -6
  12. inc/templates/edit-form.tpl.php +13 -0
  13. js/build/field-attachment.js +0 -456
  14. js/build/field-color.js +0 -323
  15. js/build/field-post-select.js +0 -202
  16. js/build/shortcode-ui.js +570 -209
  17. js/src/collections/shortcode-attributes.js +2 -1
  18. js/src/field-attachment.js +0 -152
  19. js/src/field-color.js +0 -19
  20. js/src/models/shortcode.js +7 -6
  21. js/src/utils/shortcode-view-constructor.js +7 -3
  22. js/src/utils/sui.js +1 -1
  23. js/src/views/edit-attribute-field-attachment.js +201 -0
  24. js/src/views/edit-attribute-field-color.js +54 -0
  25. js/src/{field-post-select.js → views/edit-attribute-field-post-select.js} +10 -15
  26. js/src/views/edit-attribute-field.js +57 -18
  27. js/src/views/edit-shortcode-form.js +12 -5
  28. js/src/views/insert-shortcode-list-item.js +5 -5
  29. js/src/views/insert-shortcode-list.js +3 -2
  30. js/src/views/media-frame.js +1 -4
  31. js/src/views/search-shortcode.js +2 -2
  32. js/src/views/shortcode-preview.js +4 -3
  33. js/src/views/shortcode-ui.js +2 -24
  34. js/src/views/tabbed-view.js +0 -122
  35. languages/shortcode-ui-pt_BR.mo +0 -0
  36. languages/shortcode-ui-pt_BR.po +73 -0
  37. languages/shortcode-ui-ru_RU.mo +0 -0
  38. languages/shortcode-ui-ru_RU.po +94 -0
  39. languages/shortcode-ui.pot +24 -20
  40. package.json +1 -1
  41. readme.txt +19 -2
  42. shortcode-ui.php +2 -2
.jshintrc ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "boss": true,
3
+ "curly": true,
4
+ "eqeqeq": true,
5
+ "eqnull": true,
6
+ "es3": true,
7
+ "expr": true,
8
+ "immed": true,
9
+ "noarg": true,
10
+ "onevar": true,
11
+ "quotmark": "single",
12
+ "trailing": true,
13
+ "undef": true,
14
+ "unused": true,
15
+
16
+ "browser": true,
17
+
18
+ "globals": {
19
+ "_": false,
20
+ "Backbone": false,
21
+ "jQuery": false,
22
+ "JSON": false,
23
+ "wp": false
24
+ }
25
+ }
Gruntfile.js CHANGED
@@ -54,6 +54,10 @@ module.exports = function( grunt ) {
54
  }
55
  },
56
 
 
 
 
 
57
  browserify : {
58
 
59
  options: {
@@ -92,10 +96,7 @@ module.exports = function( grunt ) {
92
 
93
  dist: {
94
  files : {
95
- 'js/build/shortcode-ui.js' : ['js/src/shortcode-ui.js'],
96
- 'js/build/field-attachment.js' : ['js/src/field-attachment.js'],
97
- 'js/build/field-color.js' : ['js/src/field-color.js'],
98
- 'js/build/field-post-select.js' : ['js/src/field-post-select.js'],
99
  },
100
  options: {
101
  transform: ['browserify-shim']
@@ -178,8 +179,9 @@ module.exports = function( grunt ) {
178
  grunt.loadNpmTasks( 'grunt-wp-i18n' );
179
  grunt.loadNpmTasks( 'grunt-wp-readme-to-markdown' );
180
  grunt.loadNpmTasks( 'grunt-contrib-jasmine' );
 
181
 
182
- grunt.registerTask( 'scripts', [ 'browserify', 'jasmine' ] );
183
  grunt.registerTask( 'styles', [ 'sass' ] );
184
  grunt.registerTask( 'default', [ 'scripts', 'styles' ] );
185
  grunt.registerTask( 'i18n', ['addtextdomain', 'makepot'] );
54
  }
55
  },
56
 
57
+ jshint: {
58
+ uses_defaults: ['js/src/**/*.js', 'js-tests/src/**/*.js']
59
+ },
60
+
61
  browserify : {
62
 
63
  options: {
96
 
97
  dist: {
98
  files : {
99
+ 'js/build/shortcode-ui.js' : ['js/src/shortcode-ui.js']
 
 
 
100
  },
101
  options: {
102
  transform: ['browserify-shim']
179
  grunt.loadNpmTasks( 'grunt-wp-i18n' );
180
  grunt.loadNpmTasks( 'grunt-wp-readme-to-markdown' );
181
  grunt.loadNpmTasks( 'grunt-contrib-jasmine' );
182
+ grunt.loadNpmTasks( 'grunt-contrib-jshint' );
183
 
184
+ grunt.registerTask( 'scripts', [ 'browserify', 'jasmine', 'jshint' ] );
185
  grunt.registerTask( 'styles', [ 'sass' ] );
186
  grunt.registerTask( 'default', [ 'scripts', 'styles' ] );
187
  grunt.registerTask( 'i18n', ['addtextdomain', 'makepot'] );
css/sass/_field-image.scss CHANGED
@@ -11,6 +11,11 @@
11
  display: none;
12
  }
13
 
 
 
 
 
 
14
  &:not( .has-attachment ) {
15
  border: 2px dashed #DDD;
16
  border-radius: 2px;
@@ -104,6 +109,14 @@
104
 
105
  }
106
 
 
 
 
 
 
 
 
 
107
  @-webkit-keyframes attachment-preview-loading {
108
  0% {
109
  margin-left: -60px;
11
  display: none;
12
  }
13
 
14
+ .thumbnail:hover:after {
15
+ background: rgba(0,0,0,0.1);
16
+ transition: all .3s linear;
17
+ }
18
+
19
  &:not( .has-attachment ) {
20
  border: 2px dashed #DDD;
21
  border-radius: 2px;
109
 
110
  }
111
 
112
+ .edit-shortcode-form .thumbnail-details-container {
113
+ display: none;
114
+
115
+ &.has-attachment {
116
+ display: block;
117
+ }
118
+ }
119
+
120
  @-webkit-keyframes attachment-preview-loading {
121
  0% {
122
  margin-left: -60px;
css/sass/shortcode-ui.scss CHANGED
@@ -81,11 +81,11 @@
81
  padding: 10px;
82
  border-top: 1px solid #ddd;
83
  }
84
-
85
  a.wp-color-result {
86
  border-bottom: 1px solid #ccc;
87
  }
88
-
89
  .media-toolbar {
90
  position: relative;
91
  height: auto;
@@ -114,6 +114,17 @@
114
  max-width: 100%;
115
  }
116
 
 
 
 
 
 
 
 
 
 
 
 
117
  textarea {
118
  width: 100%;
119
  max-width: 100%;
@@ -139,6 +150,9 @@
139
  padding-top: 10px;
140
  }
141
 
 
 
 
142
  }
143
 
144
  @import 'field-image';
81
  padding: 10px;
82
  border-top: 1px solid #ddd;
83
  }
84
+
85
  a.wp-color-result {
86
  border-bottom: 1px solid #ccc;
87
  }
88
+
89
  .media-toolbar {
90
  position: relative;
91
  height: auto;
114
  max-width: 100%;
115
  }
116
 
117
+ input[type="range"] {
118
+ -webkit-box-shadow: none;
119
+ box-shadow: none;
120
+ }
121
+
122
+ output.range {
123
+ display: inline-block;
124
+ padding: 6px 8px;
125
+ vertical-align: top;
126
+ }
127
+
128
  textarea {
129
  width: 100%;
130
  max-width: 100%;
150
  padding-top: 10px;
151
  }
152
 
153
+ .description {
154
+ clear: both;
155
+ }
156
  }
157
 
158
  @import 'field-image';
css/shortcode-ui.css CHANGED
@@ -76,6 +76,13 @@
76
  -webkit-transition: 0.05s border-color ease-in-out;
77
  transition: 0.05s border-color ease-in-out;
78
  max-width: 100%; }
 
 
 
 
 
 
 
79
  .edit-shortcode-form textarea {
80
  width: 100%;
81
  max-width: 100%;
@@ -91,6 +98,8 @@
91
  padding-top: 10px; }
92
  .edit-shortcode-form .field-inline label {
93
  display: inline-block; }
 
 
94
 
95
  .edit-shortcode-form .shortcake-attachment-preview {
96
  width: 150px;
@@ -101,6 +110,9 @@
101
  padding: 0; }
102
  .edit-shortcode-form .shortcake-attachment-preview:before {
103
  display: none; }
 
 
 
104
  .edit-shortcode-form .shortcake-attachment-preview:not(.has-attachment) {
105
  border: 2px dashed #DDD;
106
  border-radius: 2px;
@@ -165,6 +177,11 @@
165
  .edit-shortcode-form .shortcake-attachment-preview.has-attachment .button.remove {
166
  display: block; }
167
 
 
 
 
 
 
168
  @-webkit-keyframes attachment-preview-loading {
169
  0% {
170
  margin-left: -60px; }
76
  -webkit-transition: 0.05s border-color ease-in-out;
77
  transition: 0.05s border-color ease-in-out;
78
  max-width: 100%; }
79
+ .edit-shortcode-form input[type="range"] {
80
+ -webkit-box-shadow: none;
81
+ box-shadow: none; }
82
+ .edit-shortcode-form output.range {
83
+ display: inline-block;
84
+ padding: 6px 8px;
85
+ vertical-align: top; }
86
  .edit-shortcode-form textarea {
87
  width: 100%;
88
  max-width: 100%;
98
  padding-top: 10px; }
99
  .edit-shortcode-form .field-inline label {
100
  display: inline-block; }
101
+ .edit-shortcode-form .description {
102
+ clear: both; }
103
 
104
  .edit-shortcode-form .shortcake-attachment-preview {
105
  width: 150px;
110
  padding: 0; }
111
  .edit-shortcode-form .shortcake-attachment-preview:before {
112
  display: none; }
113
+ .edit-shortcode-form .shortcake-attachment-preview .thumbnail:hover:after {
114
+ background: rgba(0, 0, 0, 0.1);
115
+ transition: all .3s linear; }
116
  .edit-shortcode-form .shortcake-attachment-preview:not(.has-attachment) {
117
  border: 2px dashed #DDD;
118
  border-radius: 2px;
177
  .edit-shortcode-form .shortcake-attachment-preview.has-attachment .button.remove {
178
  display: block; }
179
 
180
+ .edit-shortcode-form .thumbnail-details-container {
181
+ display: none; }
182
+ .edit-shortcode-form .thumbnail-details-container.has-attachment {
183
+ display: block; }
184
+
185
  @-webkit-keyframes attachment-preview-loading {
186
  0% {
187
  margin-left: -60px; }
css/shortcode-ui.css.map CHANGED
@@ -6,6 +6,6 @@
6
  "../_field-image.scss"
7
  ],
8
  "sourcesContent": [],
9
- "mappings": "AAAA,AAAY,AAAO;EAClB,AAAc;;AAKf,AAA2B;EACzB,AAAW;EACX,AAAY;EACZ,AAAQ;AAGV,AAA2B;EACzB,AAAK;;AAKP;EACC,AAAS;EAEV,AAAoB;IAElB,AAAQ;IACR,AAAO;IAEP,AAAsD;IACtD,AAA8C;IAC9C,AAAY;IACZ,AAAQ;IACR,AAAU;IACV,AAAY;IACZ,AAAO;IACP,AAAQ;IAEV,AAAoB,AAAqB;MAEtC,AAAW;MACX,AAAa;MACb,AAAgB;MAEnB,AAAoB,AAAqB,AAA8B;QACnE,AAAS;QACT,AAAW;QACX,AAAa;QACb,AAAO;QACP,AAAQ;QACR,AAAU;QACV,AAAK;IAKT,AAAoB,AAAqB;MACtC,AAAQ;MACR,AAAS;MACT,AAAU;MACV,AAAM;MACN,AAAO;MACP,AAAQ;MACR,AAAU;MACV,AAAY;MACZ,AAAW;MACX,AAAY;MACZ,AAAa;MACb,AAAY;MACZ,AAAoB;MACpB,AAAY;;AAOf,AAAsB;EACpB,AAAQ;EACR,AAAS;AAGX,AAAsB;EACpB,AAAS;EACT,AAAY;AAGd,AAAsB,AAAC;EACrB,AAAe;AAGjB,AAAsB;EACpB,AAAU;EACV,AAAQ;;AAIV;EAEC,AAAS;EAEV,AAAqB;IACnB,AAAS;IACT,AAAO;EAGT,AAAqB,AAAO,AAAqB;IAE/C,AAAQ;IACR,AAAoB;IACpB,AAAY;IACZ,AAAkB;IAClB,AAAO;IACP,AAAS;IACT,AAAoB;IACpB,AAAY;IACZ,AAAW;EAGb,AAAqB;IACnB,AAAO;IACP,AAAW;IACX,AAAY;EAId,AAAqB,AAA8B;IAAzC,AAAe;EAGzB,AAAqB;IACnB,AAAS;IACX,AAAqB,AAAa;MAC/B,AAAS;MACT,AAAe;EAIlB,AAAqB;IAInB,AAAa;IAHf,AAAqB,AAAc;MAChC,AAAS;;ACxIZ,AAAqB;EAEpB,AAAO;EACP,AAAQ;EACR,AAAQ;EACR,AAAa;EACb,AAAY;EACZ,AAAS;EAEV,AAAqB,AAA6B;IAChD,AAAS;EAGX,AAAqB,AAA6B,AAAK;IACrD,AAAQ;IACR,AAAe;IACf,AAAY;IACZ,AAAY;EAGd,AAAqB,AAA8B,AAAO;IACxD,AAAgB;IAChB,AAAS;EAGX,AAAqB,AAA8B,AAAO;IAExD,AAAS;IACT,AAAS;IACT,AAAU;IACV,AAAK;IACL,AAAO;IACP,AAAQ;IACR,AAAY;IACZ,AAAa;IACb,AAAY;IACZ,AAAO;IACP,AAAQ;IACR,AAAS;IACT,AAAS;IAEX,AAAqB,AAA8B,AAAO,AAAO;MAC9D,AAAS;MACT,AAAU;MACV,AAAK;MACL,AAAM;MACN,AAAW;MACX,AAAa;EAIhB,AAAqB,AAA8B,AAAoB,AAAqB,AAA6B,AAAS,AAAO;IAEvI,AAAS;EAGX,AAAqB,AAA6B,AAAS;IACzD,AAAS;IACT,AAAU;IACV,AAAO;IACP,AAAQ;EAIV,AAAqB,AAA8B,AAAmB;IACnE,AAAW;IACX,AAAQ;IACR,AAAa;IACb,AAAO;IACP,AAAY;IACZ,AAAgB;EAEnB,AAAqB,AAA8B,AAAmB;IACnE,AAAO;IACP,AAAQ;IACR,AAAU;IACV,AAAkB;IAClB,AAAQ;IAEX,AAAqB,AAA8B,AAAmB,AAA4B;MAC9F,AAAkB;MAClB,AAAQ;MACR,AAAO;MACP,AAAQ;MACR,AAAS;MACT,AAAmB;MACnB,AAAW;EAKf,AAAqB,AAA8B;IACjD,AAAa;EAIf,AAAqB,AAA6B,AAAgB,AAAO;IACtE,AAAS;EAEZ,AAAqB,AAA6B,AAAgB,AAAO;IACtE,AAAS;;mBAMO;EACnB;IACE,AAAa;;EAEf;IACE,AAAa;;WAIJ;EACX;IACE,AAAa;;EAEf;IACE,AAAa",
10
  "names": []
11
  }
6
  "../_field-image.scss"
7
  ],
8
  "sourcesContent": [],
9
+ "mappings": "AAAA,AAAY,AAAO;EAClB,AAAc;;AAKf,AAA2B;EACzB,AAAW;EACX,AAAY;EACZ,AAAQ;AAGV,AAA2B;EACzB,AAAK;;AAKP;EACC,AAAS;EAEV,AAAoB;IAElB,AAAQ;IACR,AAAO;IAEP,AAAsD;IACtD,AAA8C;IAC9C,AAAY;IACZ,AAAQ;IACR,AAAU;IACV,AAAY;IACZ,AAAO;IACP,AAAQ;IAEV,AAAoB,AAAqB;MAEtC,AAAW;MACX,AAAa;MACb,AAAgB;MAEnB,AAAoB,AAAqB,AAA8B;QACnE,AAAS;QACT,AAAW;QACX,AAAa;QACb,AAAO;QACP,AAAQ;QACR,AAAU;QACV,AAAK;IAKT,AAAoB,AAAqB;MACtC,AAAQ;MACR,AAAS;MACT,AAAU;MACV,AAAM;MACN,AAAO;MACP,AAAQ;MACR,AAAU;MACV,AAAY;MACZ,AAAW;MACX,AAAY;MACZ,AAAa;MACb,AAAY;MACZ,AAAoB;MACpB,AAAY;;AAOf,AAAsB;EACpB,AAAQ;EACR,AAAS;AAGX,AAAsB;EACpB,AAAS;EACT,AAAY;AAGd,AAAsB,AAAC;EACrB,AAAe;AAGjB,AAAsB;EACpB,AAAU;EACV,AAAQ;;AAIV;EAEC,AAAS;EAEV,AAAqB;IACnB,AAAS;IACT,AAAO;EAGT,AAAqB,AAAO,AAAqB;IAE/C,AAAQ;IACR,AAAoB;IACpB,AAAY;IACZ,AAAkB;IAClB,AAAO;IACP,AAAS;IACT,AAAoB;IACpB,AAAY;IACZ,AAAW;EAGb,AAAqB,AAAK;IACxB,AAAoB;IACpB,AAAY;EAGd,AAAqB,AAAM;IACzB,AAAS;IACT,AAAS;IACT,AAAgB;EAGlB,AAAqB;IACnB,AAAO;IACP,AAAW;IACX,AAAY;EAId,AAAqB,AAA8B;IAAzC,AAAe;EAGzB,AAAqB;IACnB,AAAS;IACX,AAAqB,AAAa;MAC/B,AAAS;MACT,AAAe;EAIlB,AAAqB;IAInB,AAAa;IAHf,AAAqB,AAAc;MAChC,AAAS;EAKZ,AAAqB;IACnB,AAAO;;ACzJT,AAAqB;EAEpB,AAAO;EACP,AAAQ;EACR,AAAQ;EACR,AAAa;EACb,AAAY;EACZ,AAAS;EAEV,AAAqB,AAA6B;IAChD,AAAS;EAGX,AAAqB,AAA8B,AAAU,AAAM;IACjE,AAAY;IACZ,AAAY;EAGd,AAAqB,AAA6B,AAAK;IACrD,AAAQ;IACR,AAAe;IACf,AAAY;IACZ,AAAY;EAGd,AAAqB,AAA8B,AAAO;IACxD,AAAgB;IAChB,AAAS;EAGX,AAAqB,AAA8B,AAAO;IAExD,AAAS;IACT,AAAS;IACT,AAAU;IACV,AAAK;IACL,AAAO;IACP,AAAQ;IACR,AAAY;IACZ,AAAa;IACb,AAAY;IACZ,AAAO;IACP,AAAQ;IACR,AAAS;IACT,AAAS;IAEX,AAAqB,AAA8B,AAAO,AAAO;MAC9D,AAAS;MACT,AAAU;MACV,AAAK;MACL,AAAM;MACN,AAAW;MACX,AAAa;EAIhB,AAAqB,AAA8B,AAAoB,AAAqB,AAA6B,AAAS,AAAO;IAEvI,AAAS;EAGX,AAAqB,AAA6B,AAAS;IACzD,AAAS;IACT,AAAU;IACV,AAAO;IACP,AAAQ;EAIV,AAAqB,AAA8B,AAAmB;IACnE,AAAW;IACX,AAAQ;IACR,AAAa;IACb,AAAO;IACP,AAAY;IACZ,AAAgB;EAEnB,AAAqB,AAA8B,AAAmB;IACnE,AAAO;IACP,AAAQ;IACR,AAAU;IACV,AAAkB;IAClB,AAAQ;IAEX,AAAqB,AAA8B,AAAmB,AAA4B;MAC9F,AAAkB;MAClB,AAAQ;MACR,AAAO;MACP,AAAQ;MACR,AAAS;MACT,AAAmB;MACnB,AAAW;EAKf,AAAqB,AAA8B;IACjD,AAAa;EAIf,AAAqB,AAA6B,AAAgB,AAAO;IACtE,AAAS;EAEZ,AAAqB,AAA6B,AAAgB,AAAO;IACtE,AAAS;;AAMZ,AAAqB;EACpB,AAAS;EAEV,AAAqB,AAA4B;IAC/C,AAAS;;mBAIQ;EACnB;IACE,AAAa;;EAEf;IACE,AAAa;;WAIJ;EACX;IACE,AAAa;;EAEf;IACE,AAAa",
10
  "names": []
11
  }
inc/class-shortcode-ui.php CHANGED
@@ -1,37 +1,106 @@
1
  <?php
2
 
 
 
 
3
  class Shortcode_UI {
4
 
 
 
 
 
 
 
5
  private $plugin_dir;
 
 
 
 
 
 
 
6
  private $plugin_url;
7
 
 
 
 
 
 
 
8
  private $shortcodes = array();
9
 
 
 
 
 
 
 
10
  private static $instance;
11
 
 
 
 
 
 
 
 
12
  public static function get_instance() {
13
  if ( ! isset( self::$instance ) ) {
14
  self::$instance = new self;
15
  self::$instance->setup_actions();
16
  }
17
-
18
  return self::$instance;
19
  }
20
 
21
- function __construct() {
22
-
 
 
23
  $this->plugin_version = SHORTCODE_UI_VERSION;
24
  $this->plugin_dir = plugin_dir_path( dirname( __FILE__ ) );
25
  $this->plugin_url = plugin_dir_url( dirname( __FILE__ ) );
26
-
27
  }
28
 
 
 
 
29
  private function setup_actions() {
30
  add_action( 'admin_enqueue_scripts', array( $this, 'action_admin_enqueue_scripts' ) );
31
  add_action( 'wp_enqueue_editor', array( $this, 'action_wp_enqueue_editor' ) );
32
  add_action( 'wp_ajax_do_shortcode', array( $this, 'handle_ajax_do_shortcode' ) );
 
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  public function register_shortcode_ui( $shortcode_tag, $args = array() ) {
36
 
37
  // inner_content=true is a valid argument, but we want more detail
@@ -51,41 +120,63 @@ class Shortcode_UI {
51
 
52
  }
53
 
 
 
 
 
 
54
  public function get_shortcodes() {
 
 
 
 
 
 
 
55
  return apply_filters( 'shortcode_ui_shortcodes', $this->shortcodes );
56
  }
57
 
 
 
 
 
 
58
  public function get_shortcode( $shortcode_tag ) {
59
 
60
  $shortcodes = $this->get_shortcodes();
61
  if ( isset( $shortcodes[ $shortcode_tag ] ) ) {
62
  return $shortcodes[ $shortcode_tag ];
63
  }
64
-
65
  }
66
 
67
  /**
68
- * Action admin scripts.
 
 
 
 
69
  */
70
- public function action_admin_enqueue_scripts() {
71
- // Editor styles needs to be added before wp_enqueue_editor
72
  add_editor_style( trailingslashit( $this->plugin_url ) . 'css/shortcode-ui-editor-styles.css' );
73
  }
74
 
 
 
 
75
  public function enqueue() {
76
 
77
  if ( did_action( 'enqueue_shortcode_ui' ) ) {
78
  return;
79
  }
80
 
81
- // make sure media library is queued
82
  wp_enqueue_media();
83
 
84
  $shortcodes = array_values( $this->get_shortcodes() );
85
- $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
86
- if ( $screen && ! empty( $screen->post_type ) ) {
87
  foreach ( $shortcodes as $key => $args ) {
88
- if ( ! empty( $args['post_type'] ) && ! in_array( $screen->post_type, $args['post_type'] ) ) {
89
  unset( $shortcodes[ $key ] );
90
  }
91
  }
@@ -113,7 +204,6 @@ class Shortcode_UI {
113
  'media_frame_toolbar_update_label' => esc_html__( 'Update', 'shortcode-ui' ),
114
  'media_frame_no_attributes_message' => esc_html__( 'There are no attributes to configure for this Post Element.', 'shortcode-ui' ),
115
  'edit_tab_label' => esc_html__( 'Edit', 'shortcode-ui' ),
116
- 'preview_tab_label' => esc_html__( 'Preview', 'shortcode-ui' ),
117
  'mce_view_error' => esc_html__( 'Failed to load preview', 'shortcode-ui' ),
118
  'search_placeholder' => esc_html__( 'Search', 'shortcode-ui' ),
119
  'insert_content_label' => esc_html__( 'Insert Content', 'shortcode-ui' ),
@@ -124,37 +214,49 @@ class Shortcode_UI {
124
  ),
125
  ) );
126
 
127
- // queue templates
128
  add_action( 'admin_print_footer_scripts', array( $this, 'action_admin_print_footer_scripts' ) );
129
 
 
 
 
 
 
130
  do_action( 'enqueue_shortcode_ui' );
131
  }
132
 
133
  /**
134
- * Default hook to queue shortcake from
135
  */
136
  public function action_wp_enqueue_editor() {
137
- // queue scripts & templates
138
  $this->enqueue();
139
-
 
 
 
 
140
  do_action( 'shortcode_ui_loaded_editor' );
141
  }
142
 
143
  /**
144
- * Output required underscore.js templates
145
- *
146
- * @return null
147
  */
148
  public function action_admin_print_footer_scripts() {
149
  echo $this->get_view( 'media-frame' ); // WPCS: xss ok
150
  echo $this->get_view( 'list-item' ); // WPCS: xss ok
151
  echo $this->get_view( 'edit-form' ); // WPCS: xss ok
152
 
 
 
 
 
 
153
  do_action( 'print_shortcode_ui_templates' );
154
  }
155
 
156
  /**
157
  * Helper function for displaying a PHP template file.
 
158
  * Template args array is extracted and passed to the template file.
159
  *
160
  * @param string $template full template file path. Or name of template file in inc/templates.
@@ -179,7 +281,7 @@ class Shortcode_UI {
179
  }
180
 
181
  /**
182
- * Compare shortcodes by label
183
  *
184
  * @param array $a
185
  * @param array $b
@@ -190,10 +292,7 @@ class Shortcode_UI {
190
  }
191
 
192
  /**
193
- * Output a shortcode.
194
- * ajax callback for displaying the shortcode in the TinyMCE editor.
195
- *
196
- * @return null
197
  */
198
  public function handle_ajax_do_shortcode() {
199
 
@@ -223,8 +322,18 @@ class Shortcode_UI {
223
  }
224
 
225
  ob_start();
 
 
 
 
 
226
  do_action( 'shortcode_ui_before_do_shortcode', $shortcode );
227
  echo do_shortcode( $shortcode ); // WPCS: xss ok
 
 
 
 
 
228
  do_action( 'shortcode_ui_after_do_shortcode', $shortcode );
229
 
230
  wp_send_json_success( ob_get_clean() );
1
  <?php
2
 
3
+ /**
4
+ * Primary controller class for Shortcake
5
+ */
6
  class Shortcode_UI {
7
 
8
+ /**
9
+ * Path to the plugin directory.
10
+ *
11
+ * @access private
12
+ * @var string
13
+ */
14
  private $plugin_dir;
15
+
16
+ /**
17
+ * Plugin URL.
18
+ *
19
+ * @access private
20
+ * @var string
21
+ */
22
  private $plugin_url;
23
 
24
+ /**
25
+ * Shortcodes with registered shortcode UI.
26
+ *
27
+ * @access private
28
+ * @var array
29
+ */
30
  private $shortcodes = array();
31
 
32
+ /**
33
+ * Shortcake controller instance.
34
+ *
35
+ * @access private
36
+ * @var object
37
+ */
38
  private static $instance;
39
 
40
+ /**
41
+ * Get instance of Shortcake controller.
42
+ *
43
+ * Instantiates object on the fly when not already loaded.
44
+ *
45
+ * @return object
46
+ */
47
  public static function get_instance() {
48
  if ( ! isset( self::$instance ) ) {
49
  self::$instance = new self;
50
  self::$instance->setup_actions();
51
  }
 
52
  return self::$instance;
53
  }
54
 
55
+ /**
56
+ * Set up instance attributes when initially loaded.
57
+ */
58
+ private function __construct() {
59
  $this->plugin_version = SHORTCODE_UI_VERSION;
60
  $this->plugin_dir = plugin_dir_path( dirname( __FILE__ ) );
61
  $this->plugin_url = plugin_dir_url( dirname( __FILE__ ) );
 
62
  }
63
 
64
+ /**
65
+ * Setup plugin actions.
66
+ */
67
  private function setup_actions() {
68
  add_action( 'admin_enqueue_scripts', array( $this, 'action_admin_enqueue_scripts' ) );
69
  add_action( 'wp_enqueue_editor', array( $this, 'action_wp_enqueue_editor' ) );
70
  add_action( 'wp_ajax_do_shortcode', array( $this, 'handle_ajax_do_shortcode' ) );
71
+ add_filter( 'wp_editor_settings', array( $this, 'filter_wp_editor_settings' ), 10, 2 );
72
  }
73
 
74
+ /**
75
+ * When a WP_Editor is initialized on a page, call the 'register_shortcode_ui' action.
76
+ *
77
+ * This action can be used to register styles and shortcode UI for any
78
+ * shortcake-powered shortcodes, only on views which actually include a WP
79
+ * Editor.
80
+ */
81
+ public function filter_wp_editor_settings( $settings, $editor_id ) {
82
+
83
+ if ( ! did_action( 'register_shortcode_ui' ) ) {
84
+
85
+ /**
86
+ * Register shortcode UI for shortcodes.
87
+ *
88
+ * Can be used to register shortcode UI only when an editor is being enqueued.
89
+ *
90
+ * @param array $settings Settings array for the ective WP_Editor.
91
+ */
92
+ do_action( 'register_shortcode_ui', $settings, $editor_id );
93
+ }
94
+
95
+ return $settings;
96
+ }
97
+
98
+ /**
99
+ * Register UI for a shortcode.
100
+ *
101
+ * @param string $shortcode_tag Tag used for the shortcode.
102
+ * @param array $args Configuration parameters for shortcode UI.
103
+ */
104
  public function register_shortcode_ui( $shortcode_tag, $args = array() ) {
105
 
106
  // inner_content=true is a valid argument, but we want more detail
120
 
121
  }
122
 
123
+ /**
124
+ * Get configuration parameters for all shortcodes with UI.
125
+ *
126
+ * @return array
127
+ */
128
  public function get_shortcodes() {
129
+ /**
130
+ * Filter the returned shortcode UI configuration parameters.
131
+ *
132
+ * Used to remove shortcode UI that's already been registered.
133
+ *
134
+ * @param array $shortcodes
135
+ */
136
  return apply_filters( 'shortcode_ui_shortcodes', $this->shortcodes );
137
  }
138
 
139
+ /**
140
+ * Get UI configuration parameters for a given shortcode.
141
+ *
142
+ * @return array|false
143
+ */
144
  public function get_shortcode( $shortcode_tag ) {
145
 
146
  $shortcodes = $this->get_shortcodes();
147
  if ( isset( $shortcodes[ $shortcode_tag ] ) ) {
148
  return $shortcodes[ $shortcode_tag ];
149
  }
150
+ return false;
151
  }
152
 
153
  /**
154
+ * Enqueue scripts and styles used in the admin.
155
+ *
156
+ * Editor styles needs to be added before wp_enqueue_editor.
157
+ *
158
+ * @param array $editor_supports Whether or not the editor being enqueued has 'tinymce' or 'quicktags'
159
  */
160
+ public function action_admin_enqueue_scripts( $editor_supports ) {
 
161
  add_editor_style( trailingslashit( $this->plugin_url ) . 'css/shortcode-ui-editor-styles.css' );
162
  }
163
 
164
+ /**
165
+ * Enqueue scripts and styles needed for shortcode UI.
166
+ */
167
  public function enqueue() {
168
 
169
  if ( did_action( 'enqueue_shortcode_ui' ) ) {
170
  return;
171
  }
172
 
 
173
  wp_enqueue_media();
174
 
175
  $shortcodes = array_values( $this->get_shortcodes() );
176
+ $current_post_type = get_post_type();
177
+ if ( $current_post_type ) {
178
  foreach ( $shortcodes as $key => $args ) {
179
+ if ( ! empty( $args['post_type'] ) && ! in_array( $current_post_type, $args['post_type'] ) ) {
180
  unset( $shortcodes[ $key ] );
181
  }
182
  }
204
  'media_frame_toolbar_update_label' => esc_html__( 'Update', 'shortcode-ui' ),
205
  'media_frame_no_attributes_message' => esc_html__( 'There are no attributes to configure for this Post Element.', 'shortcode-ui' ),
206
  'edit_tab_label' => esc_html__( 'Edit', 'shortcode-ui' ),
 
207
  'mce_view_error' => esc_html__( 'Failed to load preview', 'shortcode-ui' ),
208
  'search_placeholder' => esc_html__( 'Search', 'shortcode-ui' ),
209
  'insert_content_label' => esc_html__( 'Insert Content', 'shortcode-ui' ),
214
  ),
215
  ) );
216
 
217
+ // add templates to the footer, instead of where we're at now
218
  add_action( 'admin_print_footer_scripts', array( $this, 'action_admin_print_footer_scripts' ) );
219
 
220
+ /**
221
+ * Fires after shortcode UI assets have been enqueued.
222
+ *
223
+ * Will only fire once per page load.
224
+ */
225
  do_action( 'enqueue_shortcode_ui' );
226
  }
227
 
228
  /**
229
+ * Enqueue shortcode UI assets when the editor is enqueued.
230
  */
231
  public function action_wp_enqueue_editor() {
 
232
  $this->enqueue();
233
+ /**
234
+ * Fires after shortcode UI assets have been loaded for the editor.
235
+ *
236
+ * Will fire every time the editor is loaded.
237
+ */
238
  do_action( 'shortcode_ui_loaded_editor' );
239
  }
240
 
241
  /**
242
+ * Output required underscore.js templates in the footer
 
 
243
  */
244
  public function action_admin_print_footer_scripts() {
245
  echo $this->get_view( 'media-frame' ); // WPCS: xss ok
246
  echo $this->get_view( 'list-item' ); // WPCS: xss ok
247
  echo $this->get_view( 'edit-form' ); // WPCS: xss ok
248
 
249
+ /**
250
+ * Fires after base shortcode UI templates have been loaded.
251
+ *
252
+ * Allows custom shortcode UI field types to load their own templates.
253
+ */
254
  do_action( 'print_shortcode_ui_templates' );
255
  }
256
 
257
  /**
258
  * Helper function for displaying a PHP template file.
259
+ *
260
  * Template args array is extracted and passed to the template file.
261
  *
262
  * @param string $template full template file path. Or name of template file in inc/templates.
281
  }
282
 
283
  /**
284
+ * Sort labels alphabetically.
285
  *
286
  * @param array $a
287
  * @param array $b
292
  }
293
 
294
  /**
295
+ * Render a shortcode for preview in the TinyMCE editor.
 
 
 
296
  */
297
  public function handle_ajax_do_shortcode() {
298
 
322
  }
323
 
324
  ob_start();
325
+ /**
326
+ * Fires before shortcode is rendered in preview.
327
+ *
328
+ * @param string $shortcode Full shortcode including attributes
329
+ */
330
  do_action( 'shortcode_ui_before_do_shortcode', $shortcode );
331
  echo do_shortcode( $shortcode ); // WPCS: xss ok
332
+ /**
333
+ * Fires after shortcode is rendered in preview.
334
+ *
335
+ * @param string $shortcode Full shortcode including attributes
336
+ */
337
  do_action( 'shortcode_ui_after_do_shortcode', $shortcode );
338
 
339
  wp_send_json_success( ob_get_clean() );
inc/fields/class-field-attachment.php CHANGED
@@ -1,13 +1,32 @@
1
  <?php
2
 
 
 
 
3
  class Shortcake_Field_Attachment {
4
 
 
 
 
 
 
 
5
  private static $instance;
6
 
7
- // All registered post fields.
 
 
 
 
 
8
  private $post_fields = array();
9
 
10
- // Field Settings.
 
 
 
 
 
11
  private $fields = array(
12
  'attachment' => array(
13
  'template' => 'fusion-shortcake-field-attachment',
@@ -15,6 +34,13 @@ class Shortcake_Field_Attachment {
15
  ),
16
  );
17
 
 
 
 
 
 
 
 
18
  public static function get_instance() {
19
  if ( ! isset( self::$instance ) ) {
20
  self::$instance = new self;
@@ -23,25 +49,31 @@ class Shortcake_Field_Attachment {
23
  return self::$instance;
24
  }
25
 
 
 
 
26
  private function setup_actions() {
27
-
28
  add_filter( 'shortcode_ui_fields', array( $this, 'filter_shortcode_ui_fields' ) );
29
  add_action( 'enqueue_shortcode_ui', array( $this, 'action_enqueue_shortcode_ui' ) );
30
  add_action( 'shortcode_ui_loaded_editor', array( $this, 'action_shortcode_ui_loaded_editor' ) );
31
-
32
  }
33
 
 
 
 
 
 
 
34
  public function filter_shortcode_ui_fields( $fields ) {
35
  return array_merge( $fields, $this->fields );
36
  }
37
 
 
 
 
38
  public function action_enqueue_shortcode_ui() {
39
 
40
- $script = plugins_url( 'js/build/field-attachment.js', dirname( dirname( __FILE__ ) ) );
41
-
42
- wp_enqueue_script( 'shortcake-field-attachment', $script, array( 'shortcode-ui' ) );
43
-
44
- wp_localize_script( 'shortcake-field-attachment', 'ShortcakeImageFieldData', array(
45
  'defaultArgs' => array(
46
  'libraryType' => null, // array of mime types. eg image, image/jpg, application, application/pdf.
47
  'addButton' => __( 'Select Attachment', 'shortcode-ui' ),
@@ -68,6 +100,17 @@ class Shortcake_Field_Attachment {
68
  <div class="attachment-preview-loading"><ins></ins></div>
69
  </div>
70
  </div>
 
 
 
 
 
 
 
 
 
 
 
71
  </div>
72
  </script>
73
 
1
  <?php
2
 
3
+ /**
4
+ * Primary controller class for Shortcake Attachment Field
5
+ */
6
  class Shortcake_Field_Attachment {
7
 
8
+ /**
9
+ * Shortcake Attachment Field controller instance.
10
+ *
11
+ * @access private
12
+ * @var object
13
+ */
14
  private static $instance;
15
 
16
+ /**
17
+ * All registered post fields.
18
+ *
19
+ * @access private
20
+ * @var array
21
+ */
22
  private $post_fields = array();
23
 
24
+ /**
25
+ * Settings for the Attachment Field.
26
+ *
27
+ * @access private
28
+ * @var array
29
+ */
30
  private $fields = array(
31
  'attachment' => array(
32
  'template' => 'fusion-shortcake-field-attachment',
34
  ),
35
  );
36
 
37
+ /**
38
+ * Get instance of Shortcake Attachment Field controller.
39
+ *
40
+ * Instantiates object on the fly when not already loaded.
41
+ *
42
+ * @return object
43
+ */
44
  public static function get_instance() {
45
  if ( ! isset( self::$instance ) ) {
46
  self::$instance = new self;
49
  return self::$instance;
50
  }
51
 
52
+ /**
53
+ * Set up actions needed for Attachment Field
54
+ */
55
  private function setup_actions() {
 
56
  add_filter( 'shortcode_ui_fields', array( $this, 'filter_shortcode_ui_fields' ) );
57
  add_action( 'enqueue_shortcode_ui', array( $this, 'action_enqueue_shortcode_ui' ) );
58
  add_action( 'shortcode_ui_loaded_editor', array( $this, 'action_shortcode_ui_loaded_editor' ) );
 
59
  }
60
 
61
+ /**
62
+ * Add Attachment Field settings to Shortcake fields
63
+ *
64
+ * @param array $fields
65
+ * @return array
66
+ */
67
  public function filter_shortcode_ui_fields( $fields ) {
68
  return array_merge( $fields, $this->fields );
69
  }
70
 
71
+ /**
72
+ * Add localization data needed for Shortcake Attachment Field
73
+ */
74
  public function action_enqueue_shortcode_ui() {
75
 
76
+ wp_localize_script( 'shortcode-ui', 'ShortcakeImageFieldData', array(
 
 
 
 
77
  'defaultArgs' => array(
78
  'libraryType' => null, // array of mime types. eg image, image/jpg, application, application/pdf.
79
  'addButton' => __( 'Select Attachment', 'shortcode-ui' ),
100
  <div class="attachment-preview-loading"><ins></ins></div>
101
  </div>
102
  </div>
103
+ <div class="thumbnail-details-container">
104
+ <strong><?php esc_html_e( 'Thumbnail Details', 'shortcode-ui' ); ?></strong>
105
+ <div class="filename"></div>
106
+ <div class="date-formatted"></div>
107
+ <div class="size"></div>
108
+ <div class="dimensions"></div>
109
+ <div class="edit-link"><a href="#"><?php esc_html_e( 'Edit Attachment', 'shortcode-ui' ); ?></a></div>
110
+ </div>
111
+ <# if ( typeof data.description == 'string' ) { #>
112
+ <p class="description">{{ data.description }}</p>
113
+ <# } #>
114
  </div>
115
  </script>
116
 
inc/fields/class-field-color.php CHANGED
@@ -1,13 +1,32 @@
1
  <?php
2
 
 
 
 
3
  class Shortcake_Field_Color {
4
 
 
 
 
 
 
 
5
  private static $instance;
6
 
7
- // All registered post fields.
 
 
 
 
 
8
  private $post_fields = array();
9
 
10
- // Field Settings.
 
 
 
 
 
11
  private $fields = array(
12
  'color' => array(
13
  'template' => 'fusion-shortcake-field-color',
@@ -15,6 +34,13 @@ class Shortcake_Field_Color {
15
  ),
16
  );
17
 
 
 
 
 
 
 
 
18
  public static function get_instance() {
19
  if ( ! isset( self::$instance ) ) {
20
  self::$instance = new self;
@@ -23,14 +49,19 @@ class Shortcake_Field_Color {
23
  return self::$instance;
24
  }
25
 
 
 
 
26
  private function setup_actions() {
27
-
28
  add_filter( 'shortcode_ui_fields', array( $this, 'filter_shortcode_ui_fields' ) );
29
- add_action( 'admin_enqueue_scripts', array( $this, 'action_admin_enqueue_scripts' ), 100 );
30
  add_action( 'shortcode_ui_loaded_editor', array( $this, 'load_template' ) );
31
-
32
  }
33
 
 
 
 
 
 
34
  private function color_attribute_present() {
35
 
36
  foreach ( Shortcode_UI::get_instance()->get_shortcodes() as $shortcode ) {
@@ -51,25 +82,18 @@ class Shortcake_Field_Color {
51
  }
52
 
53
  return false;
54
-
55
  }
56
 
 
 
 
 
 
 
57
  public function filter_shortcode_ui_fields( $fields ) {
58
  return array_merge( $fields, $this->fields );
59
  }
60
 
61
- public function action_admin_enqueue_scripts() {
62
-
63
- if ( ! $this->color_attribute_present() ) {
64
- return;
65
- }
66
-
67
- $script = plugins_url( 'js/build/field-color.js', dirname( dirname( __FILE__ ) ) );
68
-
69
- wp_enqueue_script( 'shortcake-field-color', $script, array( 'shortcode-ui' ) );
70
-
71
- }
72
-
73
  /**
74
  * Output templates used by the color field.
75
  */
1
  <?php
2
 
3
+ /**
4
+ * Primary controller class for Shortcake Color Field
5
+ */
6
  class Shortcake_Field_Color {
7
 
8
+ /**
9
+ * Shortcake Color Field controller instance.
10
+ *
11
+ * @access private
12
+ * @var object
13
+ */
14
  private static $instance;
15
 
16
+ /**
17
+ * All registered post fields.
18
+ *
19
+ * @access private
20
+ * @var array
21
+ */
22
  private $post_fields = array();
23
 
24
+ /**
25
+ * Settings for the Color Field.
26
+ *
27
+ * @access private
28
+ * @var array
29
+ */
30
  private $fields = array(
31
  'color' => array(
32
  'template' => 'fusion-shortcake-field-color',
34
  ),
35
  );
36
 
37
+ /**
38
+ * Get instance of Shortcake Color Field controller.
39
+ *
40
+ * Instantiates object on the fly when not already loaded.
41
+ *
42
+ * @return object
43
+ */
44
  public static function get_instance() {
45
  if ( ! isset( self::$instance ) ) {
46
  self::$instance = new self;
49
  return self::$instance;
50
  }
51
 
52
+ /**
53
+ * Set up actions needed for Color Field
54
+ */
55
  private function setup_actions() {
 
56
  add_filter( 'shortcode_ui_fields', array( $this, 'filter_shortcode_ui_fields' ) );
 
57
  add_action( 'shortcode_ui_loaded_editor', array( $this, 'load_template' ) );
 
58
  }
59
 
60
+ /**
61
+ * Whether or not the color attribute is present in registered shortcode UI
62
+ *
63
+ * @return bool
64
+ */
65
  private function color_attribute_present() {
66
 
67
  foreach ( Shortcode_UI::get_instance()->get_shortcodes() as $shortcode ) {
82
  }
83
 
84
  return false;
 
85
  }
86
 
87
+ /**
88
+ * Add Color Field settings to Shortcake fields
89
+ *
90
+ * @param array $fields
91
+ * @return array
92
+ */
93
  public function filter_shortcode_ui_fields( $fields ) {
94
  return array_merge( $fields, $this->fields );
95
  }
96
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  /**
98
  * Output templates used by the color field.
99
  */
inc/fields/class-field-post-select.php CHANGED
@@ -40,16 +40,10 @@ class Shortcode_UI_Field_Post_Select {
40
 
41
  $plugin_dir = dirname( dirname( __FILE__ ) );
42
 
43
- wp_enqueue_script(
44
- 'shortcode-ui-field-post-select',
45
- plugins_url( 'js/build/field-post-select.js', $plugin_dir ),
46
- array( 'shortcode-ui', 'select2' )
47
- );
48
-
49
  wp_enqueue_script( 'select2', plugins_url( 'lib/select2/select2.min.js', $plugin_dir ) , array( 'jquery', 'jquery-ui-sortable' ), '3.5.2' );
50
  wp_enqueue_style( 'select2', plugins_url( 'lib/select2/select2.css', $plugin_dir ), null, '3.5.2' );
51
 
52
- wp_localize_script( 'shortcode-ui-field-post-select', 'shortcodeUiPostFieldData', array(
53
  'nonce' => wp_create_nonce( 'shortcode_ui_field_post_select' ),
54
  ) );
55
 
40
 
41
  $plugin_dir = dirname( dirname( __FILE__ ) );
42
 
 
 
 
 
 
 
43
  wp_enqueue_script( 'select2', plugins_url( 'lib/select2/select2.min.js', $plugin_dir ) , array( 'jquery', 'jquery-ui-sortable' ), '3.5.2' );
44
  wp_enqueue_style( 'select2', plugins_url( 'lib/select2/select2.css', $plugin_dir ), null, '3.5.2' );
45
 
46
+ wp_localize_script( 'shortcode-ui', 'shortcodeUiPostFieldData', array(
47
  'nonce' => wp_create_nonce( 'shortcode_ui_field_post_select' ),
48
  ) );
49
 
inc/fields/class-shortcode-ui-fields.php CHANGED
@@ -1,16 +1,35 @@
1
  <?php
2
 
 
 
 
3
  class Shortcode_UI_Fields {
4
 
 
 
 
 
 
 
5
  private static $instance;
6
 
7
- // Default Field Settings.
 
 
 
 
 
8
  private $field_defaults = array(
9
  'template' => 'shortcode-ui-field-text',
10
  'view' => 'editAttributeField',
11
  );
12
 
13
- // Field Settings.
 
 
 
 
 
14
  private $fields = array(
15
  'text' => array(),
16
  'textarea' => array(
@@ -37,8 +56,18 @@ class Shortcode_UI_Fields {
37
  'date' => array(
38
  'template' => 'shortcode-ui-field-date',
39
  ),
 
 
 
40
  );
41
 
 
 
 
 
 
 
 
42
  public static function get_instance() {
43
  if ( ! isset( self::$instance ) ) {
44
  self::$instance = new self;
@@ -47,14 +76,16 @@ class Shortcode_UI_Fields {
47
  return self::$instance;
48
  }
49
 
 
 
 
50
  private function setup_actions() {
51
  add_action( 'init', array( $this, 'action_init' ) );
52
  add_action( 'enqueue_shortcode_ui', array( $this, 'action_enqueue_shortcode_ui' ), 100 );
53
  }
54
 
55
  /**
56
- * Init.
57
- * @return null
58
  */
59
  public function action_init() {
60
 
@@ -81,10 +112,11 @@ class Shortcode_UI_Fields {
81
  return $this->fields;
82
  }
83
 
 
 
 
84
  public function action_enqueue_shortcode_ui() {
85
-
86
  wp_localize_script( 'shortcode-ui', 'shortcodeUIFieldData', $this->fields );
87
-
88
  }
89
 
90
  }
1
  <?php
2
 
3
+ /**
4
+ * Primary controller class for default Shortcake fields
5
+ */
6
  class Shortcode_UI_Fields {
7
 
8
+ /**
9
+ * Shortcake Fields controller instance.
10
+ *
11
+ * @access private
12
+ * @var object
13
+ */
14
  private static $instance;
15
 
16
+ /**
17
+ * Default settings for each field
18
+ *
19
+ * @access private
20
+ * @var array
21
+ */
22
  private $field_defaults = array(
23
  'template' => 'shortcode-ui-field-text',
24
  'view' => 'editAttributeField',
25
  );
26
 
27
+ /**
28
+ * Settings for default Fields.
29
+ *
30
+ * @access private
31
+ * @var array
32
+ */
33
  private $fields = array(
34
  'text' => array(),
35
  'textarea' => array(
56
  'date' => array(
57
  'template' => 'shortcode-ui-field-date',
58
  ),
59
+ 'range' => array(
60
+ 'template' => 'shortcode-ui-field-range',
61
+ ),
62
  );
63
 
64
+ /**
65
+ * Get instance of Shortcake Field controller.
66
+ *
67
+ * Instantiates object on the fly when not already loaded.
68
+ *
69
+ * @return object
70
+ */
71
  public static function get_instance() {
72
  if ( ! isset( self::$instance ) ) {
73
  self::$instance = new self;
76
  return self::$instance;
77
  }
78
 
79
+ /**
80
+ * Set up actions needed for default fields
81
+ */
82
  private function setup_actions() {
83
  add_action( 'init', array( $this, 'action_init' ) );
84
  add_action( 'enqueue_shortcode_ui', array( $this, 'action_enqueue_shortcode_ui' ), 100 );
85
  }
86
 
87
  /**
88
+ * Perform setup actions.
 
89
  */
90
  public function action_init() {
91
 
112
  return $this->fields;
113
  }
114
 
115
+ /**
116
+ * Add localization data needed for default fields
117
+ */
118
  public function action_enqueue_shortcode_ui() {
 
119
  wp_localize_script( 'shortcode-ui', 'shortcodeUIFieldData', $this->fields );
 
120
  }
121
 
122
  }
inc/templates/edit-form.tpl.php CHANGED
@@ -135,3 +135,16 @@
135
  <# } #>
136
  </div>
137
  </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  <# } #>
136
  </div>
137
  </script>
138
+
139
+ <script type="text/html" id="tmpl-shortcode-ui-field-range">
140
+ <div class="field-block">
141
+ <label for="{{ data.id }}">{{ data.label }}</label>
142
+ <div class="field-range-container">
143
+ <input type="range" name="{{ data.attr }}" id="{{ data.id }}" value="{{ data.value}}" {{{ data.meta }}} />
144
+ <output class="range" for="{{ data.id }}" id="{{ data.id }}_indicator">{{ data.value }}</output>
145
+ </div>
146
+ <# if ( typeof data.description == 'string' ) { #>
147
+ <p class="description">{{ data.description }}</p>
148
+ <# } #>
149
+ </div>
150
+ </script>
js/build/field-attachment.js DELETED
@@ -1,456 +0,0 @@
1
- (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
- (function (global){
3
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
4
- var ShortcodeAttribute = require('./../models/shortcode-attribute.js');
5
-
6
- /**
7
- * Shortcode Attributes collection.
8
- */
9
- var ShortcodeAttributes = Backbone.Collection.extend({
10
- model : ShortcodeAttribute,
11
- // Deep Clone.
12
- clone : function() {
13
- return new this.constructor(_.map(this.models, function(m) {
14
- return m.clone();
15
- }));
16
- }
17
- });
18
-
19
- module.exports = ShortcodeAttributes;
20
-
21
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
22
- },{"./../models/shortcode-attribute.js":5}],2:[function(require,module,exports){
23
- (function (global){
24
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
25
- var Shortcode = require('./../models/shortcode.js');
26
-
27
- // Shortcode Collection
28
- var Shortcodes = Backbone.Collection.extend({
29
- model : Shortcode
30
- });
31
-
32
- module.exports = Shortcodes;
33
-
34
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
35
- },{"./../models/shortcode.js":6}],3:[function(require,module,exports){
36
- (function (global){
37
- var sui = require('./utils/sui.js'),
38
- editAttributeField = require('./views/edit-attribute-field.js'),
39
- $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
40
-
41
- // Cache attachment IDs for quicker loading.
42
- var iDCache = {};
43
-
44
- sui.views.editAttributeFieldAttachment = editAttributeField.extend( {
45
-
46
- render: function() {
47
-
48
- var model = this.model;
49
-
50
- // Set model default values.
51
- for ( var arg in ShortcakeImageFieldData.defaultArgs ) {
52
- if ( ! model.get( arg ) ) {
53
- model.set( arg, ShortcakeImageFieldData.defaultArgs[ arg ] );
54
- }
55
- }
56
-
57
- this.$el.html( this.template( model.toJSON() ) );
58
-
59
- var $container = this.$el.find( '.shortcake-attachment-preview' );
60
- var $addButton = $container.find( 'button.add' );
61
- var $removeButton = $container.find( 'button.remove' );
62
-
63
- var frame = wp.media( {
64
- multiple: false,
65
- title: model.get( 'frameTitle' ),
66
- library: {
67
- type: model.get( 'libraryType' ),
68
- },
69
- } );
70
-
71
- /**
72
- * Update the field attachment.
73
- * Re-renders UI.
74
- * If ID is empty - does nothing.
75
- *
76
- * @param {int} id Attachment ID
77
- */
78
- var updateAttachment = function( id ) {
79
-
80
- if ( ! id ) {
81
- return;
82
- }
83
-
84
- model.set( 'value', id );
85
-
86
- if ( iDCache[ id ] ) {
87
- renderPreview( iDCache[ id ] );
88
- return;
89
- }
90
-
91
- $container.addClass( 'loading' );
92
-
93
- wp.ajax.post( 'get-attachment', {
94
- 'id': id
95
- } ).done( function( attachment ) {
96
- // Cache for later.
97
- iDCache[ id ] = attachment;
98
- renderPreview( attachment );
99
- $container.removeClass( 'loading' );
100
- } );
101
-
102
- }
103
-
104
- /**
105
- * Renders attachment preview in field.
106
- * @param {object} attachment model
107
- * @return null
108
- */
109
- var renderPreview = function( attachment ) {
110
-
111
- var $thumbnail = $('<div class="thumbnail"></div>');
112
-
113
- if ( 'image' !== attachment.type ) {
114
-
115
- $( '<img/>', {
116
- src: attachment.icon,
117
- alt: attachment.title,
118
- } ).appendTo( $thumbnail );
119
-
120
- $( '<div/>', {
121
- class: 'filename',
122
- html: '<div>' + attachment.title + '</div>',
123
- } ).appendTo( $thumbnail );
124
-
125
- } else {
126
-
127
- attachmentThumb = (typeof attachment.sizes.thumbnail !== 'undefined') ?
128
- attachment.sizes.thumbnail :
129
- _.first( _.sortBy( attachment.sizes, 'width' ) );
130
-
131
- $( '<img/>', {
132
- src: attachmentThumb.url,
133
- width: attachmentThumb.width,
134
- height: attachmentThumb.height,
135
- alt: attachment.alt,
136
- } ) .appendTo( $thumbnail )
137
-
138
- }
139
-
140
- $thumbnail.find( 'img' ).wrap( '<div class="centered"></div>' );
141
- $container.append( $thumbnail );
142
- $container.toggleClass( 'has-attachment', true );
143
-
144
- }
145
-
146
- /**
147
- * Remove the attachment.
148
- * Render preview & Update the model.
149
- */
150
- var removeAttachment = function() {
151
-
152
- model.set( 'value', null );
153
-
154
- $container.toggleClass( 'has-attachment', false );
155
- $container.toggleClass( 'has-attachment', false );
156
- $container.find( '.thumbnail' ).remove();
157
- }
158
-
159
- // Add initial Attachment if available.
160
- updateAttachment( model.get( 'value' ) );
161
-
162
- // Remove file when the button is clicked.
163
- $removeButton.click( function(e) {
164
- e.preventDefault();
165
- removeAttachment();
166
- });
167
-
168
- // Open media frame when add button is clicked
169
- $addButton.click( function(e) {
170
- e.preventDefault();
171
- frame.open();
172
- } );
173
-
174
- // Update the attachment when an item is selected.
175
- frame.on( 'select', function() {
176
-
177
- var selection = frame.state().get('selection');
178
- attachment = selection.first();
179
-
180
- updateAttachment( attachment.id );
181
-
182
- frame.close();
183
-
184
- });
185
-
186
- }
187
-
188
- } );
189
-
190
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
191
- },{"./utils/sui.js":7,"./views/edit-attribute-field.js":8}],4:[function(require,module,exports){
192
- (function (global){
193
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
194
-
195
- /**
196
- * Shortcode Attribute Model.
197
- */
198
- var InnerContent = Backbone.Model.extend({
199
- defaults : {
200
- label: shortcodeUIData.strings.insert_content_label,
201
- type: 'textarea',
202
- value: '',
203
- placeholder: '',
204
- },
205
- });
206
-
207
- module.exports = InnerContent;
208
-
209
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
210
- },{}],5:[function(require,module,exports){
211
- (function (global){
212
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
213
-
214
- var ShortcodeAttribute = Backbone.Model.extend({
215
- defaults: {
216
- attr: '',
217
- label: '',
218
- type: '',
219
- value: '',
220
- description: '',
221
- meta: {
222
- placeholder: '',
223
- },
224
- },
225
- });
226
-
227
- module.exports = ShortcodeAttribute;
228
-
229
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
230
- },{}],6:[function(require,module,exports){
231
- (function (global){
232
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
233
- var ShortcodeAttributes = require('./../collections/shortcode-attributes.js');
234
- var InnerContent = require('./inner-content.js');
235
-
236
- Shortcode = Backbone.Model.extend({
237
-
238
- defaults: {
239
- label: '',
240
- shortcode_tag: '',
241
- attrs: new ShortcodeAttributes,
242
- },
243
-
244
- /**
245
- * Custom set method.
246
- * Handles setting the attribute collection.
247
- */
248
- set: function( attributes, options ) {
249
-
250
- if ( attributes.attrs !== undefined && ! ( attributes.attrs instanceof ShortcodeAttributes ) ) {
251
- attributes.attrs = new ShortcodeAttributes( attributes.attrs );
252
- }
253
-
254
- if ( attributes.inner_content && ! ( attributes.inner_content instanceof InnerContent ) ) {
255
- attributes.inner_content = new InnerContent( attributes.inner_content );
256
- }
257
-
258
- return Backbone.Model.prototype.set.call(this, attributes, options);
259
- },
260
-
261
- /**
262
- * Custom toJSON.
263
- * Handles converting the attribute collection to JSON.
264
- */
265
- toJSON: function( options ) {
266
- options = Backbone.Model.prototype.toJSON.call(this, options);
267
- if ( options.attrs && ( options.attrs instanceof ShortcodeAttributes ) ) {
268
- options.attrs = options.attrs.toJSON();
269
- }
270
- if ( options.inner_content && ( options.inner_content instanceof InnerContent ) ) {
271
- options.inner_content = options.inner_content.toJSON();
272
- }
273
- return options;
274
- },
275
-
276
- /**
277
- * Custom clone
278
- * Make sure we don't clone a reference to attributes.
279
- */
280
- clone: function() {
281
- var clone = Backbone.Model.prototype.clone.call( this );
282
- clone.set( 'attrs', clone.get( 'attrs' ).clone() );
283
- if ( clone.get( 'inner_content' ) ) {
284
- clone.set( 'inner_content', clone.get( 'inner_content' ).clone() );
285
- }
286
- return clone;
287
- },
288
-
289
- /**
290
- * Get the shortcode as... a shortcode!
291
- *
292
- * @return string eg [shortcode attr1=value]
293
- */
294
- formatShortcode: function() {
295
-
296
- var template, shortcodeAttributes, attrs = [], content, self = this;
297
-
298
- this.get( 'attrs' ).each( function( attr ) {
299
-
300
- // Skip empty attributes.
301
- if ( ! attr.get( 'value' ) || attr.get( 'value' ).length < 1 ) {
302
- return;
303
- }
304
-
305
- attrs.push( attr.get( 'attr' ) + '="' + attr.get( 'value' ) + '"' );
306
-
307
- } );
308
-
309
- if ( this.get( 'inner_content' ) ) {
310
- content = this.get( 'inner_content' ).get( 'value' );
311
- }
312
-
313
- if ( attrs.length > 0 ) {
314
- template = "[{{ shortcode }} {{ attributes }}]"
315
- } else {
316
- template = "[{{ shortcode }}]"
317
- }
318
-
319
- if ( content && content.length > 0 ) {
320
- template += "{{ content }}[/{{ shortcode }}]"
321
- }
322
-
323
- template = template.replace( /{{ shortcode }}/g, this.get('shortcode_tag') );
324
- template = template.replace( /{{ attributes }}/g, attrs.join( ' ' ) );
325
- template = template.replace( /{{ content }}/g, content );
326
-
327
- return template;
328
-
329
- }
330
-
331
- });
332
-
333
- module.exports = Shortcode;
334
-
335
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
336
- },{"./../collections/shortcode-attributes.js":1,"./inner-content.js":4}],7:[function(require,module,exports){
337
- var Shortcodes = require('./../collections/shortcodes.js');
338
-
339
- window.Shortcode_UI = window.Shortcode_UI || {
340
- shortcodes: new Shortcodes,
341
- views: {},
342
- controllers: {},
343
- };
344
-
345
- module.exports = window.Shortcode_UI;
346
-
347
- },{"./../collections/shortcodes.js":2}],8:[function(require,module,exports){
348
- (function (global){
349
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
350
- sui = require('./../utils/sui.js'),
351
- $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
352
-
353
- var editAttributeField = Backbone.View.extend( {
354
-
355
- tagName: "div",
356
-
357
- events: {
358
- 'keyup input[type="text"]': 'updateValue',
359
- 'keyup textarea': 'updateValue',
360
- 'change select': 'updateValue',
361
- 'change input[type=checkbox]': 'updateValue',
362
- 'change input[type=radio]': 'updateValue',
363
- 'change input[type=email]': 'updateValue',
364
- 'change input[type=number]': 'updateValue',
365
- 'change input[type=date]': 'updateValue',
366
- 'change input[type=url]': 'updateValue',
367
- },
368
-
369
- render: function() {
370
-
371
- var data = jQuery.extend( {
372
- id: 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid,
373
- }, this.model.toJSON() );
374
-
375
- // Convert meta JSON to attribute string.
376
- var _meta = [];
377
- for ( var key in data.meta ) {
378
-
379
- // Boolean attributes can only require attribute key, not value.
380
- if ( 'boolean' === typeof( data.meta[ key ] ) ) {
381
-
382
- // Only set truthy boolean attributes.
383
- if ( data.meta[ key ] ) {
384
- _meta.push( _.escape( key ) );
385
- }
386
-
387
- } else {
388
-
389
- _meta.push( _.escape( key ) + '="' + _.escape( data.meta[ key ] ) + '"' );
390
-
391
- }
392
-
393
- }
394
-
395
- data.meta = _meta.join( ' ' );
396
-
397
- this.$el.html( this.template( data ) );
398
- this.updateValue();
399
-
400
- return this
401
- },
402
-
403
- /**
404
- * Input Changed Update Callback.
405
- *
406
- * If the input field that has changed is for content or a valid attribute,
407
- * then it should update the model. If a callback function is registered
408
- * for this attribute, it should be called as well.
409
- */
410
- updateValue: function( e ) {
411
-
412
- if ( this.model.get( 'attr' ) ) {
413
- var $el = $( this.el ).find( '[name=' + this.model.get( 'attr' ) + ']' );
414
- } else {
415
- var $el = $( this.el ).find( '[name="inner_content"]' );
416
- }
417
-
418
- if ( 'radio' === this.model.attributes.type ) {
419
- this.model.set( 'value', $el.filter(':checked').first().val() );
420
- } else if ( 'checkbox' === this.model.attributes.type ) {
421
- this.model.set( 'value', $el.is( ':checked' ) );
422
- } else {
423
- this.model.set( 'value', $el.val() );
424
- }
425
-
426
- var shortcodeName = this.shortcode.attributes.shortcode_tag,
427
- attributeName = this.model.get( 'attr' ),
428
- hookName = [ shortcodeName, attributeName ].join( '.' ),
429
- changed = this.model.changed,
430
- collection = _.flatten( _.values( this.views.parent.views._views ) ),
431
- shortcode = this.shortcode;
432
-
433
- /*
434
- * Action run when an attribute value changes on a shortcode
435
- *
436
- * Called as `{shortcodeName}.{attributeName}`.
437
- *
438
- * @param changed (object)
439
- * The update, ie. { "changed": "newValue" }
440
- * @param viewModels (array)
441
- * The collections of views (editAttributeFields)
442
- * which make up this shortcode UI form
443
- * @param shortcode (object)
444
- * Reference to the shortcode model which this attribute belongs to.
445
- */
446
- wp.shortcake.hooks.doAction( hookName, changed, collection, shortcode );
447
-
448
- }
449
-
450
- } );
451
-
452
- sui.views.editAttributeField = editAttributeField;
453
- module.exports = editAttributeField;
454
-
455
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
456
- },{"./../utils/sui.js":7}]},{},[3]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/build/field-color.js DELETED
@@ -1,323 +0,0 @@
1
- (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
- (function (global){
3
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
4
- var ShortcodeAttribute = require('./../models/shortcode-attribute.js');
5
-
6
- /**
7
- * Shortcode Attributes collection.
8
- */
9
- var ShortcodeAttributes = Backbone.Collection.extend({
10
- model : ShortcodeAttribute,
11
- // Deep Clone.
12
- clone : function() {
13
- return new this.constructor(_.map(this.models, function(m) {
14
- return m.clone();
15
- }));
16
- }
17
- });
18
-
19
- module.exports = ShortcodeAttributes;
20
-
21
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
22
- },{"./../models/shortcode-attribute.js":5}],2:[function(require,module,exports){
23
- (function (global){
24
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
25
- var Shortcode = require('./../models/shortcode.js');
26
-
27
- // Shortcode Collection
28
- var Shortcodes = Backbone.Collection.extend({
29
- model : Shortcode
30
- });
31
-
32
- module.exports = Shortcodes;
33
-
34
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
35
- },{"./../models/shortcode.js":6}],3:[function(require,module,exports){
36
- (function (global){
37
- var sui = require('./utils/sui.js'),
38
- editAttributeField = require('./views/edit-attribute-field.js'),
39
- $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
40
-
41
- sui.views.editAttributeFieldColor = editAttributeField.extend( {
42
-
43
- render: function() {
44
- this.$el.html( this.template( this.model.toJSON() ) );
45
-
46
- this.$el.find('input[type="text"]:not(.wp-color-picker)').wpColorPicker({
47
- change: function() {
48
- $(this).trigger('keyup');
49
- }
50
- });
51
-
52
- return this;
53
- }
54
-
55
- } );
56
-
57
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
58
- },{"./utils/sui.js":7,"./views/edit-attribute-field.js":8}],4:[function(require,module,exports){
59
- (function (global){
60
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
61
-
62
- /**
63
- * Shortcode Attribute Model.
64
- */
65
- var InnerContent = Backbone.Model.extend({
66
- defaults : {
67
- label: shortcodeUIData.strings.insert_content_label,
68
- type: 'textarea',
69
- value: '',
70
- placeholder: '',
71
- },
72
- });
73
-
74
- module.exports = InnerContent;
75
-
76
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
77
- },{}],5:[function(require,module,exports){
78
- (function (global){
79
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
80
-
81
- var ShortcodeAttribute = Backbone.Model.extend({
82
- defaults: {
83
- attr: '',
84
- label: '',
85
- type: '',
86
- value: '',
87
- description: '',
88
- meta: {
89
- placeholder: '',
90
- },
91
- },
92
- });
93
-
94
- module.exports = ShortcodeAttribute;
95
-
96
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
97
- },{}],6:[function(require,module,exports){
98
- (function (global){
99
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
100
- var ShortcodeAttributes = require('./../collections/shortcode-attributes.js');
101
- var InnerContent = require('./inner-content.js');
102
-
103
- Shortcode = Backbone.Model.extend({
104
-
105
- defaults: {
106
- label: '',
107
- shortcode_tag: '',
108
- attrs: new ShortcodeAttributes,
109
- },
110
-
111
- /**
112
- * Custom set method.
113
- * Handles setting the attribute collection.
114
- */
115
- set: function( attributes, options ) {
116
-
117
- if ( attributes.attrs !== undefined && ! ( attributes.attrs instanceof ShortcodeAttributes ) ) {
118
- attributes.attrs = new ShortcodeAttributes( attributes.attrs );
119
- }
120
-
121
- if ( attributes.inner_content && ! ( attributes.inner_content instanceof InnerContent ) ) {
122
- attributes.inner_content = new InnerContent( attributes.inner_content );
123
- }
124
-
125
- return Backbone.Model.prototype.set.call(this, attributes, options);
126
- },
127
-
128
- /**
129
- * Custom toJSON.
130
- * Handles converting the attribute collection to JSON.
131
- */
132
- toJSON: function( options ) {
133
- options = Backbone.Model.prototype.toJSON.call(this, options);
134
- if ( options.attrs && ( options.attrs instanceof ShortcodeAttributes ) ) {
135
- options.attrs = options.attrs.toJSON();
136
- }
137
- if ( options.inner_content && ( options.inner_content instanceof InnerContent ) ) {
138
- options.inner_content = options.inner_content.toJSON();
139
- }
140
- return options;
141
- },
142
-
143
- /**
144
- * Custom clone
145
- * Make sure we don't clone a reference to attributes.
146
- */
147
- clone: function() {
148
- var clone = Backbone.Model.prototype.clone.call( this );
149
- clone.set( 'attrs', clone.get( 'attrs' ).clone() );
150
- if ( clone.get( 'inner_content' ) ) {
151
- clone.set( 'inner_content', clone.get( 'inner_content' ).clone() );
152
- }
153
- return clone;
154
- },
155
-
156
- /**
157
- * Get the shortcode as... a shortcode!
158
- *
159
- * @return string eg [shortcode attr1=value]
160
- */
161
- formatShortcode: function() {
162
-
163
- var template, shortcodeAttributes, attrs = [], content, self = this;
164
-
165
- this.get( 'attrs' ).each( function( attr ) {
166
-
167
- // Skip empty attributes.
168
- if ( ! attr.get( 'value' ) || attr.get( 'value' ).length < 1 ) {
169
- return;
170
- }
171
-
172
- attrs.push( attr.get( 'attr' ) + '="' + attr.get( 'value' ) + '"' );
173
-
174
- } );
175
-
176
- if ( this.get( 'inner_content' ) ) {
177
- content = this.get( 'inner_content' ).get( 'value' );
178
- }
179
-
180
- if ( attrs.length > 0 ) {
181
- template = "[{{ shortcode }} {{ attributes }}]"
182
- } else {
183
- template = "[{{ shortcode }}]"
184
- }
185
-
186
- if ( content && content.length > 0 ) {
187
- template += "{{ content }}[/{{ shortcode }}]"
188
- }
189
-
190
- template = template.replace( /{{ shortcode }}/g, this.get('shortcode_tag') );
191
- template = template.replace( /{{ attributes }}/g, attrs.join( ' ' ) );
192
- template = template.replace( /{{ content }}/g, content );
193
-
194
- return template;
195
-
196
- }
197
-
198
- });
199
-
200
- module.exports = Shortcode;
201
-
202
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
203
- },{"./../collections/shortcode-attributes.js":1,"./inner-content.js":4}],7:[function(require,module,exports){
204
- var Shortcodes = require('./../collections/shortcodes.js');
205
-
206
- window.Shortcode_UI = window.Shortcode_UI || {
207
- shortcodes: new Shortcodes,
208
- views: {},
209
- controllers: {},
210
- };
211
-
212
- module.exports = window.Shortcode_UI;
213
-
214
- },{"./../collections/shortcodes.js":2}],8:[function(require,module,exports){
215
- (function (global){
216
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
217
- sui = require('./../utils/sui.js'),
218
- $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
219
-
220
- var editAttributeField = Backbone.View.extend( {
221
-
222
- tagName: "div",
223
-
224
- events: {
225
- 'keyup input[type="text"]': 'updateValue',
226
- 'keyup textarea': 'updateValue',
227
- 'change select': 'updateValue',
228
- 'change input[type=checkbox]': 'updateValue',
229
- 'change input[type=radio]': 'updateValue',
230
- 'change input[type=email]': 'updateValue',
231
- 'change input[type=number]': 'updateValue',
232
- 'change input[type=date]': 'updateValue',
233
- 'change input[type=url]': 'updateValue',
234
- },
235
-
236
- render: function() {
237
-
238
- var data = jQuery.extend( {
239
- id: 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid,
240
- }, this.model.toJSON() );
241
-
242
- // Convert meta JSON to attribute string.
243
- var _meta = [];
244
- for ( var key in data.meta ) {
245
-
246
- // Boolean attributes can only require attribute key, not value.
247
- if ( 'boolean' === typeof( data.meta[ key ] ) ) {
248
-
249
- // Only set truthy boolean attributes.
250
- if ( data.meta[ key ] ) {
251
- _meta.push( _.escape( key ) );
252
- }
253
-
254
- } else {
255
-
256
- _meta.push( _.escape( key ) + '="' + _.escape( data.meta[ key ] ) + '"' );
257
-
258
- }
259
-
260
- }
261
-
262
- data.meta = _meta.join( ' ' );
263
-
264
- this.$el.html( this.template( data ) );
265
- this.updateValue();
266
-
267
- return this
268
- },
269
-
270
- /**
271
- * Input Changed Update Callback.
272
- *
273
- * If the input field that has changed is for content or a valid attribute,
274
- * then it should update the model. If a callback function is registered
275
- * for this attribute, it should be called as well.
276
- */
277
- updateValue: function( e ) {
278
-
279
- if ( this.model.get( 'attr' ) ) {
280
- var $el = $( this.el ).find( '[name=' + this.model.get( 'attr' ) + ']' );
281
- } else {
282
- var $el = $( this.el ).find( '[name="inner_content"]' );
283
- }
284
-
285
- if ( 'radio' === this.model.attributes.type ) {
286
- this.model.set( 'value', $el.filter(':checked').first().val() );
287
- } else if ( 'checkbox' === this.model.attributes.type ) {
288
- this.model.set( 'value', $el.is( ':checked' ) );
289
- } else {
290
- this.model.set( 'value', $el.val() );
291
- }
292
-
293
- var shortcodeName = this.shortcode.attributes.shortcode_tag,
294
- attributeName = this.model.get( 'attr' ),
295
- hookName = [ shortcodeName, attributeName ].join( '.' ),
296
- changed = this.model.changed,
297
- collection = _.flatten( _.values( this.views.parent.views._views ) ),
298
- shortcode = this.shortcode;
299
-
300
- /*
301
- * Action run when an attribute value changes on a shortcode
302
- *
303
- * Called as `{shortcodeName}.{attributeName}`.
304
- *
305
- * @param changed (object)
306
- * The update, ie. { "changed": "newValue" }
307
- * @param viewModels (array)
308
- * The collections of views (editAttributeFields)
309
- * which make up this shortcode UI form
310
- * @param shortcode (object)
311
- * Reference to the shortcode model which this attribute belongs to.
312
- */
313
- wp.shortcake.hooks.doAction( hookName, changed, collection, shortcode );
314
-
315
- }
316
-
317
- } );
318
-
319
- sui.views.editAttributeField = editAttributeField;
320
- module.exports = editAttributeField;
321
-
322
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
323
- },{"./../utils/sui.js":7}]},{},[3]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/build/field-post-select.js DELETED
@@ -1,202 +0,0 @@
1
- (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
- ( function( $ ) {
3
-
4
- var sui = window.Shortcode_UI;
5
-
6
- // Cached Data.
7
- var postSelectCache = {};
8
-
9
- sui.views.editAttributeFieldPostSelect = sui.views.editAttributeField.extend( {
10
-
11
- events: {
12
- 'change .shortcode-ui-post-select': 'updateValue',
13
- },
14
-
15
- render: function() {
16
-
17
- var self = this,
18
- defaults = { multiple: false };
19
-
20
- for ( var arg in defaults ) {
21
- if ( ! this.model.get( arg ) ) {
22
- this.model.set( arg, defaults[ arg ] );
23
- }
24
- }
25
-
26
- var data = this.model.toJSON();
27
- data.id = 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid;
28
-
29
- this.$el.html( this.template( data ) );
30
-
31
- var ajaxData = {
32
- action : 'shortcode_ui_post_field',
33
- nonce : shortcodeUiPostFieldData.nonce,
34
- shortcode : this.shortcode.get( 'shortcode_tag'),
35
- attr : this.model.get( 'attr' )
36
- };
37
-
38
- var $field = this.$el.find( '.shortcode-ui-post-select' );
39
-
40
- $field.select2({
41
-
42
- placeholder: "Search",
43
- multiple: this.model.get( 'multiple' ),
44
- ajax: {
45
- url: ajaxurl,
46
- dataType: 'json',
47
- quietMillis: 250,
48
- data: function (term, page) {
49
- ajaxData.s = term;
50
- ajaxData.page = page;
51
- return ajaxData;
52
- },
53
- results: function ( response, page ) {
54
-
55
- if ( ! response.success ) {
56
- return { results: {}, more: false };
57
- }
58
-
59
- // Cache data for quicker rendering later.
60
- postSelectCache = $.extend( postSelectCache, response.data.posts );
61
-
62
- var more = ( page * response.data.posts_per_page ) < response.data.found_posts; // whether or not there are more results available
63
- return { results: response.data.posts, more: more };
64
-
65
- },
66
- },
67
-
68
- /**
69
- * Initialize Callback
70
- * Used to set render the initial value.
71
- * Has to make a request to get the title for the current ID.
72
- */
73
- initSelection: function(element, callback) {
74
-
75
- var ids, parsedData = [], cached;
76
-
77
- // Convert stored value to array of IDs (int).
78
- ids = $(element)
79
- .val()
80
- .split(',')
81
- .map( function (str) { return str.trim(); } )
82
- .map( function (str) { return parseInt( str ); } )
83
-
84
- if ( ids.length < 1 ) {
85
- return;
86
- }
87
-
88
- // Check if there is already cached data.
89
- for ( var i = 0; i < ids.length; i++ ) {
90
- if ( cached = _.find( postSelectCache, _.matches( { id: ids[i] } ) ) ) {
91
- parsedData.push( cached );
92
- }
93
- };
94
-
95
- // If not multiple - return single value if we have one.
96
- if ( parsedData.length && ! self.model.get( 'multiple' ) ) {
97
- callback( parsedData[0] );
98
- return;
99
- }
100
-
101
- var uncachedIds = _.difference( ids, _.pluck( parsedData, 'id' ) );
102
-
103
- if ( ! uncachedIds.length ) {
104
-
105
- callback( parsedData );
106
-
107
- } else {
108
-
109
- var initAjaxData = jQuery.extend( true, {}, ajaxData );
110
- initAjaxData.action = 'shortcode_ui_post_field';
111
- initAjaxData.post__in = uncachedIds;
112
-
113
- $.get( ajaxurl, initAjaxData ).done( function( response ) {
114
-
115
- if ( ! response.success ) {
116
- return { results: {}, more: false };
117
- }
118
-
119
- postSelectCache = $.extend( postSelectCache, response.data.posts );
120
-
121
- // If not multi-select, expects single object, not array of objects.
122
- if ( ! self.model.get( 'multiple' ) ) {
123
- callback( response.data.posts[0] );
124
- return;
125
- }
126
-
127
- // Append new data to cached data.
128
- // Sort by original order.
129
- parsedData = parsedData
130
- .concat( response.data.posts )
131
- .sort(function (a, b) {
132
- if ( ids.indexOf( a.id ) > ids.indexOf( b.id ) ) return 1;
133
- if ( ids.indexOf( a.id ) < ids.indexOf( b.id ) ) return -1;
134
- return 0;
135
- });
136
-
137
- callback( parsedData );
138
- return;
139
-
140
- } );
141
-
142
- }
143
-
144
- },
145
-
146
- } );
147
-
148
- // Make multiple values sortable.
149
- if ( this.model.get( 'multiple' ) ) {
150
- $field.select2('container').find('ul.select2-choices').sortable({
151
- containment: 'parent',
152
- start: function() { $('.shortcode-ui-post-select').select2('onSortStart'); },
153
- update: function() { $('.shortcode-ui-post-select').select2('onSortEnd'); }
154
- });
155
- }
156
-
157
- return this;
158
-
159
- }
160
-
161
- } );
162
-
163
- /**
164
- * Extending SUI Media Controller to hide Select2 UI Drop-Down when menu
165
- * changes in Meida modal
166
- * 1. going back/forth between different shortcakes (refresh)
167
- * 2. changing the menu in left column (deactivate)
168
- * 3. @TODO closing the modal.
169
- */
170
- var mediaController = sui.controllers.MediaController;
171
- sui.controllers.MediaController = mediaController.extend({
172
-
173
- refresh: function(){
174
- mediaController.prototype.refresh.apply( this, arguments );
175
- this.destroySelect2UI();
176
- },
177
-
178
- //doesn't need to call parent as it already an "abstract" method in parent to provide callback
179
- deactivate: function() {
180
- this.destroySelect2UI();
181
- },
182
-
183
- destroySelect2UI: function() {
184
- $('.shortcode-ui-post-select.select2-container').select2( "close" );
185
- }
186
-
187
- });
188
-
189
- /**
190
- * Extending the SUI Tabbed View to hide Select2 UI dropdown when previewing the shortcake
191
- */
192
- var tabbedView = sui.views.TabbedView;
193
- sui.views.TabbedView = tabbedView.extend({
194
- tabSwitcher: function() {
195
- tabbedView.prototype.tabSwitcher.apply( this, arguments );
196
- $('.shortcode-ui-post-select.select2-container').select2( "close" );
197
- }
198
- });
199
-
200
- } )( jQuery );
201
-
202
- },{}]},{},[1]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/build/shortcode-ui.js CHANGED
@@ -13,7 +13,8 @@ var ShortcodeAttributes = Backbone.Collection.extend({
13
  return new this.constructor(_.map(this.models, function(m) {
14
  return m.clone();
15
  }));
16
- }
 
17
  });
18
 
19
  module.exports = ShortcodeAttributes;
@@ -138,7 +139,7 @@ Shortcode = Backbone.Model.extend({
138
  defaults: {
139
  label: '',
140
  shortcode_tag: '',
141
- attrs: new ShortcodeAttributes,
142
  },
143
 
144
  /**
@@ -208,16 +209,18 @@ Shortcode = Backbone.Model.extend({
208
 
209
  if ( this.get( 'inner_content' ) ) {
210
  content = this.get( 'inner_content' ).get( 'value' );
 
 
211
  }
212
 
213
  if ( attrs.length > 0 ) {
214
- template = "[{{ shortcode }} {{ attributes }}]"
215
  } else {
216
- template = "[{{ shortcode }}]"
217
  }
218
 
219
  if ( content && content.length > 0 ) {
220
- template += "{{ content }}[/{{ shortcode }}]"
221
  }
222
 
223
  template = template.replace( /{{ shortcode }}/g, this.get('shortcode_tag') );
@@ -226,8 +229,7 @@ Shortcode = Backbone.Model.extend({
226
 
227
  return template;
228
 
229
- }
230
-
231
  });
232
 
233
  module.exports = Shortcode;
@@ -264,7 +266,7 @@ $(document).ready(function(){
264
  });
265
 
266
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
267
- },{"./collections/shortcodes.js":2,"./utils/shortcode-view-constructor.js":8,"./utils/sui.js":9,"./views/media-frame.js":14}],8:[function(require,module,exports){
268
  (function (global){
269
  var sui = require('./sui.js'),
270
  wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null),
@@ -311,7 +313,7 @@ var shortcodeViewConstructor = {
311
  if ( 'content' in options ) {
312
  var innerContent = shortcodeModel.get('inner_content');
313
  if ( innerContent ) {
314
- innerContent.set('value', options.content)
315
  }
316
  }
317
 
@@ -452,7 +454,11 @@ var shortcodeViewConstructor = {
452
 
453
  if ( matches[3] ) {
454
  var inner_content = currentShortcode.get( 'inner_content' );
455
- inner_content.set( 'value', this.unAutoP( matches[3] ) );
 
 
 
 
456
  }
457
 
458
  return currentShortcode;
@@ -508,7 +514,7 @@ var shortcodeViewConstructor = {
508
  if ('content' in options.shortcode) {
509
  var inner_content = shortcode.get('inner_content');
510
  if ( inner_content ) {
511
- inner_content.set('value', options.shortcode.content)
512
  }
513
  }
514
 
@@ -594,7 +600,7 @@ module.exports = shortcodeViewConstructor;
594
  var Shortcodes = require('./../collections/shortcodes.js');
595
 
596
  window.Shortcode_UI = window.Shortcode_UI || {
597
- shortcodes: new Shortcodes,
598
  views: {},
599
  controllers: {},
600
  };
@@ -602,6 +608,463 @@ window.Shortcode_UI = window.Shortcode_UI || {
602
  module.exports = window.Shortcode_UI;
603
 
604
  },{"./../collections/shortcodes.js":2}],10:[function(require,module,exports){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  (function (global){
606
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
607
  sui = require('./../utils/sui.js'),
@@ -612,15 +1075,16 @@ var editAttributeField = Backbone.View.extend( {
612
  tagName: "div",
613
 
614
  events: {
615
- 'keyup input[type="text"]': 'updateValue',
616
- 'keyup textarea': 'updateValue',
617
- 'change select': 'updateValue',
618
- 'change input[type=checkbox]': 'updateValue',
619
- 'change input[type=radio]': 'updateValue',
620
- 'change input[type=email]': 'updateValue',
621
- 'change input[type=number]': 'updateValue',
622
- 'change input[type=date]': 'updateValue',
623
- 'change input[type=url]': 'updateValue',
 
624
  },
625
 
626
  render: function() {
@@ -652,9 +1116,9 @@ var editAttributeField = Backbone.View.extend( {
652
  data.meta = _meta.join( ' ' );
653
 
654
  this.$el.html( this.template( data ) );
655
- this.updateValue();
656
 
657
- return this
658
  },
659
 
660
  /**
@@ -664,22 +1128,42 @@ var editAttributeField = Backbone.View.extend( {
664
  * then it should update the model. If a callback function is registered
665
  * for this attribute, it should be called as well.
666
  */
667
- updateValue: function( e ) {
 
 
668
 
669
  if ( this.model.get( 'attr' ) ) {
670
- var $el = $( this.el ).find( '[name=' + this.model.get( 'attr' ) + ']' );
671
  } else {
672
- var $el = $( this.el ).find( '[name="inner_content"]' );
673
  }
674
 
675
  if ( 'radio' === this.model.attributes.type ) {
676
- this.model.set( 'value', $el.filter(':checked').first().val() );
677
  } else if ( 'checkbox' === this.model.attributes.type ) {
678
- this.model.set( 'value', $el.is( ':checked' ) );
 
 
 
 
 
679
  } else {
680
- this.model.set( 'value', $el.val() );
681
  }
682
 
 
 
 
 
 
 
 
 
 
 
 
 
 
683
  var shortcodeName = this.shortcode.attributes.shortcode_tag,
684
  attributeName = this.model.get( 'attr' ),
685
  hookName = [ shortcodeName, attributeName ].join( '.' ),
@@ -704,18 +1188,43 @@ var editAttributeField = Backbone.View.extend( {
704
 
705
  }
706
 
707
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
 
709
  sui.views.editAttributeField = editAttributeField;
710
  module.exports = editAttributeField;
711
 
712
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
713
- },{"./../utils/sui.js":9}],11:[function(require,module,exports){
714
  (function (global){
715
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null),
716
- sui = require('./../utils/sui.js'),
717
- backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
718
- editAttributeField = require('./edit-attribute-field.js');
 
 
 
 
 
 
 
719
 
720
  /**
721
  * Single edit shortcode content view.
@@ -754,7 +1263,7 @@ var EditShortcodeForm = wp.Backbone.View.extend({
754
  attr_raw: {
755
  name: attr.get('value')
756
  }
757
- }
758
 
759
  var viewObjName = shortcodeUIFieldData[ type ].view;
760
  var tmplName = shortcodeUIFieldData[ type ].template;
@@ -767,7 +1276,7 @@ var EditShortcodeForm = wp.Backbone.View.extend({
767
 
768
  } );
769
 
770
- if ( 0 == this.model.get( 'attrs' ).length && ( ! innerContent || typeof innerContent == 'undefined' ) ) {
771
  var messageView = new Backbone.View({
772
  tagName: 'div',
773
  className: 'notice updated',
@@ -787,9 +1296,10 @@ var EditShortcodeForm = wp.Backbone.View.extend({
787
  module.exports = EditShortcodeForm;
788
 
789
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
790
- },{"./../utils/sui.js":9,"./edit-attribute-field.js":10}],12:[function(require,module,exports){
791
  (function (global){
792
- var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null);
 
793
 
794
  /**
795
  * Single shortcode list item view.
@@ -805,10 +1315,9 @@ var insertShortcodeListItem = wp.Backbone.View.extend({
805
  var data = this.model.toJSON();
806
  this.$el.attr('data-shortcode', data.shortcode_tag);
807
 
808
- if (('listItemImage' in data)
809
- && 0 === data.listItemImage.indexOf('dashicons-')) {
810
- data.listItemImage = '<div class="dashicons ' + data.listItemImage
811
- + '"></div>';
812
  }
813
 
814
  this.$el.html(this.template(data));
@@ -821,7 +1330,7 @@ var insertShortcodeListItem = wp.Backbone.View.extend({
821
  module.exports = insertShortcodeListItem;
822
 
823
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
824
- },{}],13:[function(require,module,exports){
825
  (function (global){
826
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null);
827
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
@@ -840,10 +1349,11 @@ var insertShortcodeList = wp.Backbone.View.extend({
840
  },
841
 
842
  refresh: function( shortcodeData ) {
 
843
  if ( shortcodeData instanceof Backbone.Collection ) {
844
- var options = { shortcodes: shortcodeData };
845
  } else {
846
- var options = { shortcodes: new Shortcodes( shortcodeData ) };
847
  }
848
  this.displayShortcodes( options );
849
  },
@@ -867,7 +1377,7 @@ var insertShortcodeList = wp.Backbone.View.extend({
867
  module.exports = insertShortcodeList;
868
 
869
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
870
- },{"./../collections/shortcodes.js":2,"./insert-shortcode-list-item.js":12}],14:[function(require,module,exports){
871
  (function (global){
872
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null),
873
  $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null),
@@ -974,10 +1484,7 @@ var mediaFrame = postMediaFrame.extend( {
974
  // @todo - fix this.
975
  // This is a hack.
976
  // I just can't work out how to do it properly...
977
- if (
978
- view.controller.state().props
979
- && view.controller.state().props.get( 'currentShortcode' )
980
- ) {
981
  window.setTimeout( function() {
982
  view.controller.$el.addClass( 'hide-menu' );
983
  } );
@@ -994,7 +1501,7 @@ var mediaFrame = postMediaFrame.extend( {
994
  module.exports = mediaFrame;
995
 
996
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
997
- },{"./../controllers/media-controller.js":3,"./media-toolbar":15,"./shortcode-ui":18}],15:[function(require,module,exports){
998
  (function (global){
999
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null);
1000
 
@@ -1026,7 +1533,7 @@ var Toolbar = wp.media.view.Toolbar.extend({
1026
  module.exports = Toolbar;
1027
 
1028
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1029
- },{}],16:[function(require,module,exports){
1030
  (function (global){
1031
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null);
1032
  sui = require('./../utils/sui.js');
@@ -1062,7 +1569,7 @@ var SearchShortcode = wp.media.view.Search.extend({
1062
  },
1063
 
1064
  search: function( event ) {
1065
- if ( event.target.value == '' ) {
1066
  this.refreshShortcodes( sui.shortcodes );
1067
  } else {
1068
  this.refreshShortcodes( this.controller.search( event.target.value ) );
@@ -1072,8 +1579,9 @@ var SearchShortcode = wp.media.view.Search.extend({
1072
 
1073
  sui.views.SearchShortcode = SearchShortcode;
1074
  module.exports = SearchShortcode;
 
1075
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1076
- },{"./../utils/sui.js":9}],17:[function(require,module,exports){
1077
  (function (global){
1078
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
1079
  $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
@@ -1142,7 +1650,7 @@ var ShortcodePreview = Backbone.View.extend({
1142
  var isIE = typeof tinymce != 'undefined' ? tinymce.Env.ie : false;
1143
 
1144
  $iframe = $( '<iframe/>', {
1145
- src: isIE ? 'javascript:""' : '',
1146
  frameBorder: '0',
1147
  allowTransparency: 'true',
1148
  scrolling: 'no',
@@ -1245,8 +1753,9 @@ var ShortcodePreview = Backbone.View.extend({
1245
  var editors = typeof tinymce != 'undefined' ? tinymce.editors : [];
1246
  _.each( editors, function( editor ) {
1247
  _.each( editor.dom.$( 'link[rel="stylesheet"]', editor.getDoc().head ), function( link ) {
1248
- var href;
1249
- ( href = link.href ) && ( styles[href] = true ); // Poor man's de-duping.
 
1250
  });
1251
  });
1252
 
@@ -1261,11 +1770,10 @@ var ShortcodePreview = Backbone.View.extend({
1261
  module.exports = ShortcodePreview;
1262
 
1263
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1264
- },{}],18:[function(require,module,exports){
1265
  (function (global){
1266
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
1267
  insertShortcodeList = require('./insert-shortcode-list.js'),
1268
- TabbedView = require('./tabbed-view.js'),
1269
  ShortcodePreview = require('./shortcode-preview.js'),
1270
  EditShortcodeForm = require('./edit-shortcode-form.js'),
1271
  Toolbar = require('./media-toolbar.js'),
@@ -1289,7 +1797,7 @@ var Shortcode_UI = Backbone.View.extend({
1289
  createToolbar: function(options) {
1290
  toolbarOptions = {
1291
  controller: this.toolbar_controller
1292
- }
1293
 
1294
  this.toolbar = new Toolbar( toolbarOptions );
1295
 
@@ -1329,28 +1837,7 @@ var Shortcode_UI = Backbone.View.extend({
1329
 
1330
  renderEditShortcodeView: function() {
1331
  var shortcode = this.controller.props.get( 'currentShortcode' );
1332
- var view = new TabbedView({
1333
- tabs: {
1334
- edit: {
1335
- label: shortcodeUIData.strings.edit_tab_label,
1336
- content: new EditShortcodeForm({ model: shortcode })
1337
- },
1338
-
1339
- preview: {
1340
- label: shortcodeUIData.strings.preview_tab_label,
1341
- content: new ShortcodePreview({ model: shortcode }),
1342
- open: function() {
1343
- this.render();
1344
- }
1345
- }
1346
- },
1347
-
1348
- styles: {
1349
- group: 'media-router edit-shortcode-tabs',
1350
- tab: 'media-menu-item edit-shortcode-tab'
1351
- }
1352
- });
1353
-
1354
  this.$el.append( view.render().el );
1355
 
1356
  if ( this.controller.props.get('action') === 'update' ) {
@@ -1389,130 +1876,4 @@ var Shortcode_UI = Backbone.View.extend({
1389
  module.exports = Shortcode_UI;
1390
 
1391
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1392
- },{"./../utils/sui.js":9,"./edit-shortcode-form.js":11,"./insert-shortcode-list.js":13,"./media-toolbar.js":15,"./search-shortcode.js":16,"./shortcode-preview.js":17,"./tabbed-view.js":19}],19:[function(require,module,exports){
1393
- (function (global){
1394
- var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
1395
- var sui = require('./../utils/sui.js');
1396
- var $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
1397
-
1398
- /**
1399
- * Abstraction to manage tabbed content. Tab parameters (e.g., label) along with
1400
- * views for associated content are passed to initialize the tabbed view.
1401
- *
1402
- * @class TabbedView
1403
- * @constructor
1404
- * @extends Backbone.View
1405
- * @params [options]
1406
- * @params [options.tabs] {Object} A hash of key:value pairs, where each value
1407
- * is itself an object with the following properties:
1408
- *
1409
- * label: The label to display on the tab. content: The `Backbone.View`
1410
- * associated with the tab content.
1411
- */
1412
- var TabbedView = Backbone.View.extend({
1413
- template : wp.template('tabbed-view-base'),
1414
- tabs : {},
1415
-
1416
- events : {
1417
- 'click [data-role="tab"]' : function(event) {
1418
- this.tabSwitcher(event);
1419
- }
1420
- },
1421
-
1422
- initialize : function(options) {
1423
- Backbone.View.prototype.initialize.apply(this, arguments);
1424
-
1425
- _.defaults(this.options = (options || {}), {
1426
- styles : {
1427
- group : '',
1428
- tab : ''
1429
- }
1430
- });
1431
-
1432
- this.tabs = _.extend(this.tabs, options.tabs);
1433
- },
1434
-
1435
- /**
1436
- * @method render
1437
- * @chainable
1438
- * @returns {TabbedView}
1439
- */
1440
- render : function() {
1441
- var $content;
1442
-
1443
- this.$el.html(this.template({
1444
- tabs : this.tabs,
1445
- styles : this.options.styles
1446
- }));
1447
-
1448
- $content = this.$('[data-role="tab-content"]');
1449
- $content.empty();
1450
-
1451
- _.each(this.tabs, function(tab) {
1452
- var $el = tab.content.render().$el;
1453
- $el.hide();
1454
- $content.append($el);
1455
- });
1456
-
1457
- this.select(0);
1458
-
1459
- return this;
1460
- },
1461
-
1462
- /**
1463
- * Switches tab when previewing or editing
1464
- */
1465
- tabSwitcher : function(event) {
1466
- event.stopPropagation();
1467
- event.preventDefault();
1468
-
1469
- var target = $(event.currentTarget).attr('data-target');
1470
-
1471
- this.select(target);
1472
- },
1473
-
1474
- /**
1475
- * Programmatically select (activate) a specific tab. Used internally to
1476
- * process tab click events.
1477
- *
1478
- * @method select
1479
- * @param selector
1480
- * {number|string} The index (zero based) or key of the target
1481
- * tab.
1482
- */
1483
- select : function(selector) {
1484
- var index = 0;
1485
- var target = null;
1486
- var tab;
1487
-
1488
- selector = selector || 0;
1489
-
1490
- _.each(this.tabs, function(tab, key) {
1491
- tab.content.$el.hide();
1492
-
1493
- if (selector === key || selector === index) {
1494
- target = key;
1495
- }
1496
-
1497
- index = index + 1;
1498
- });
1499
-
1500
- this.$('[data-role="tab"]').removeClass('active');
1501
-
1502
- if (target) {
1503
- tab = this.tabs[target];
1504
-
1505
- this.$('[data-role="tab"][data-target="' + target + '"]').addClass(
1506
- 'active');
1507
-
1508
- tab.content.$el.show();
1509
- (typeof tab.open == 'function') && tab.open.call(tab.content);
1510
- }
1511
- }
1512
- });
1513
-
1514
- sui.views.TabbedView = TabbedView;
1515
- module.exports = TabbedView;
1516
-
1517
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1518
- },{"./../utils/sui.js":9}]},{},[7]);
13
  return new this.constructor(_.map(this.models, function(m) {
14
  return m.clone();
15
  }));
16
+ },
17
+
18
  });
19
 
20
  module.exports = ShortcodeAttributes;
139
  defaults: {
140
  label: '',
141
  shortcode_tag: '',
142
+ attrs: new ShortcodeAttributes(),
143
  },
144
 
145
  /**
209
 
210
  if ( this.get( 'inner_content' ) ) {
211
  content = this.get( 'inner_content' ).get( 'value' );
212
+ } else if ( this.get( 'inner_content_backup' ) ) {
213
+ content = this.get( 'inner_content_backup' );
214
  }
215
 
216
  if ( attrs.length > 0 ) {
217
+ template = "[{{ shortcode }} {{ attributes }}]";
218
  } else {
219
+ template = "[{{ shortcode }}]";
220
  }
221
 
222
  if ( content && content.length > 0 ) {
223
+ template += "{{ content }}[/{{ shortcode }}]";
224
  }
225
 
226
  template = template.replace( /{{ shortcode }}/g, this.get('shortcode_tag') );
229
 
230
  return template;
231
 
232
+ },
 
233
  });
234
 
235
  module.exports = Shortcode;
266
  });
267
 
268
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
269
+ },{"./collections/shortcodes.js":2,"./utils/shortcode-view-constructor.js":8,"./utils/sui.js":9,"./views/media-frame.js":17}],8:[function(require,module,exports){
270
  (function (global){
271
  var sui = require('./sui.js'),
272
  wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null),
313
  if ( 'content' in options ) {
314
  var innerContent = shortcodeModel.get('inner_content');
315
  if ( innerContent ) {
316
+ innerContent.set('value', options.content);
317
  }
318
  }
319
 
454
 
455
  if ( matches[3] ) {
456
  var inner_content = currentShortcode.get( 'inner_content' );
457
+ if ( inner_content ) {
458
+ inner_content.set( 'value', this.unAutoP( matches[3] ) );
459
+ } else {
460
+ currentShortcode.set( 'inner_content_backup', this.unAutoP( matches[3] ) );
461
+ }
462
  }
463
 
464
  return currentShortcode;
514
  if ('content' in options.shortcode) {
515
  var inner_content = shortcode.get('inner_content');
516
  if ( inner_content ) {
517
+ inner_content.set('value', options.shortcode.content);
518
  }
519
  }
520
 
600
  var Shortcodes = require('./../collections/shortcodes.js');
601
 
602
  window.Shortcode_UI = window.Shortcode_UI || {
603
+ shortcodes: new Shortcodes(),
604
  views: {},
605
  controllers: {},
606
  };
608
  module.exports = window.Shortcode_UI;
609
 
610
  },{"./../collections/shortcodes.js":2}],10:[function(require,module,exports){
611
+ var sui = require('./../utils/sui.js');
612
+
613
+ var editAttributeFieldAttachment = sui.views.editAttributeField.extend( {
614
+
615
+ events: {
616
+ 'click .add' : '_openMediaFrame',
617
+ 'click .remove' : '_removeAttachment',
618
+ 'click .thumbnail' : '_openMediaFrame',
619
+ 'selectAttachment' : '_selectAttachment',
620
+ },
621
+
622
+ /**
623
+ * Update the field attachment.
624
+ * Re-renders UI.
625
+ * If ID is empty - does nothing.
626
+ *
627
+ * @param {int} id Attachment ID
628
+ */
629
+ updateValue: function( id ) {
630
+
631
+ if ( ! id ) {
632
+ return;
633
+ }
634
+
635
+ this.setValue( id );
636
+
637
+ var self = this;
638
+
639
+ if ( editAttributeFieldAttachment.getFromCache( id ) ) {
640
+ self._renderPreview( editAttributeFieldAttachment.getFromCache( id ) );
641
+
642
+ // Call the updateValue() function, to trigger any listeners
643
+ // hooked on it.
644
+ self.triggerCallbacks();
645
+ return;
646
+ }
647
+
648
+ this.$container.addClass( 'loading' );
649
+
650
+ wp.ajax.post( 'get-attachment', {
651
+ 'id': id
652
+ } ).done( function( attachment ) {
653
+ // Cache for later.
654
+ editAttributeFieldAttachment.setInCache( id, attachment );
655
+ self._renderPreview( attachment );
656
+
657
+ // Call the updateValue() function, to trigger any listeners
658
+ // hooked on it.
659
+ self.triggerCallbacks();
660
+ } ).always( function( attachment ) {
661
+ self.$container.removeClass( 'loading' );
662
+ });
663
+ },
664
+
665
+ render: function() {
666
+
667
+ // Set model default values.
668
+ for ( var arg in ShortcakeImageFieldData.defaultArgs ) {
669
+ if ( ! this.model.get( arg ) ) {
670
+ this.model.set( arg, ShortcakeImageFieldData.defaultArgs[ arg ] );
671
+ }
672
+ }
673
+
674
+ this.$el.html( this.template( this.model.toJSON() ) );
675
+
676
+ this.$container = this.$el.find( '.shortcake-attachment-preview' );
677
+ this.$thumbnailDetailsContainer = this.$el.find( '.thumbnail-details-container' );
678
+ var $addButton = this.$container.find( 'button.add' );
679
+
680
+ this.frame = wp.media( {
681
+ multiple: false,
682
+ title: this.model.get( 'frameTitle' ),
683
+ library: {
684
+ type: this.model.get( 'libraryType' ),
685
+ },
686
+ } );
687
+
688
+ // Add initial Attachment if available.
689
+ this.updateValue( this.model.get( 'value' ) );
690
+
691
+ },
692
+
693
+ /**
694
+ * Renders attachment preview in field.
695
+ * @param {object} attachment model
696
+ * @return null
697
+ */
698
+ _renderPreview: function( attachment ) {
699
+
700
+ var $thumbnail = jQuery('<div class="thumbnail"></div>');
701
+
702
+ if ( 'image' !== attachment.type ) {
703
+
704
+ jQuery( '<img/>', {
705
+ src: attachment.icon,
706
+ alt: attachment.title,
707
+ } ).appendTo( $thumbnail );
708
+
709
+ jQuery( '<div/>', {
710
+ class: 'filename',
711
+ html: '<div>' + attachment.title + '</div>',
712
+ } ).appendTo( $thumbnail );
713
+
714
+ } else {
715
+
716
+ attachmentThumb = (typeof attachment.sizes.thumbnail !== 'undefined') ?
717
+ attachment.sizes.thumbnail :
718
+ _.first( _.sortBy( attachment.sizes, 'width' ) );
719
+
720
+ jQuery( '<img/>', {
721
+ src: attachmentThumb.url,
722
+ width: attachmentThumb.width,
723
+ height: attachmentThumb.height,
724
+ alt: attachment.alt,
725
+ } ) .appendTo( $thumbnail );
726
+
727
+ }
728
+
729
+ $thumbnail.find( 'img' ).wrap( '<div class="centered"></div>' );
730
+ this.$container.append( $thumbnail );
731
+ this.$container.toggleClass( 'has-attachment', true );
732
+
733
+ this.$thumbnailDetailsContainer.find( '.filename' ).text( attachment.filename );
734
+ this.$thumbnailDetailsContainer.find( '.date-formatted' ).text( attachment.dateFormatted );
735
+ this.$thumbnailDetailsContainer.find( '.size' ).text( attachment.filesizeHumanReadable );
736
+ this.$thumbnailDetailsContainer.find( '.dimensions' ).text( attachment.height + ' × ' + attachment.width );
737
+ this.$thumbnailDetailsContainer.find( '.edit-link a' ).attr( "href", attachment.editLink );
738
+ this.$thumbnailDetailsContainer.toggleClass( 'has-attachment', true );
739
+
740
+ },
741
+
742
+ /**
743
+ * Open media frame when add button is clicked.
744
+ *
745
+ */
746
+ _openMediaFrame: function(e) {
747
+ e.preventDefault();
748
+ this.frame.open();
749
+
750
+ var self = this;
751
+ this.frame.on( 'select', function() {
752
+ self.$el.trigger( 'selectAttachment' );
753
+ } );
754
+
755
+ },
756
+
757
+ /**
758
+ * When an attachment is selected from the media frame, update the model value.
759
+ *
760
+ */
761
+ _selectAttachment: function(e) {
762
+ var selection = this.frame.state().get('selection');
763
+ attachment = selection.first();
764
+ if ( attachment.id != this.model.get( 'value' ) ){
765
+ this.model.set( 'value', null );
766
+ this.$container.toggleClass( 'has-attachment', false );
767
+ this.$container.find( '.thumbnail' ).remove();
768
+ this.updateValue( attachment.id );
769
+ }
770
+ this.frame.close();
771
+ },
772
+
773
+ /**
774
+ * Remove the attachment.
775
+ * Render preview & Update the model.
776
+ */
777
+ _removeAttachment: function(e) {
778
+ e.preventDefault();
779
+
780
+ this.model.set( 'value', null );
781
+
782
+ this.$container.toggleClass( 'has-attachment', false );
783
+ this.$container.find( '.thumbnail' ).remove();
784
+ this.$thumbnailDetailsContainer.toggleClass( 'has-attachment', false );
785
+ },
786
+
787
+ }, {
788
+
789
+ _idCache: {},
790
+
791
+ /**
792
+ * Store attachments in a cache for quicker loading.
793
+ */
794
+ setInCache: function( id, attachment ) {
795
+ this._idCache[ id ] = attachment;
796
+ },
797
+
798
+ /**
799
+ * Retrieve an attachment from the cache.
800
+ */
801
+ getFromCache: function( id ){
802
+ if ( 'undefined' === typeof this._idCache[ id ] ) {
803
+ return false;
804
+ }
805
+ return this._idCache[ id ];
806
+ },
807
+
808
+ });
809
+
810
+ module.exports = sui.views.editAttributeFieldAttachment = editAttributeFieldAttachment;
811
+
812
+
813
+ },{"./../utils/sui.js":9}],11:[function(require,module,exports){
814
+ (function (global){
815
+ var sui = require('./../utils/sui.js'),
816
+ editAttributeField = require('./edit-attribute-field.js'),
817
+ $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
818
+
819
+ sui.views.editAttributeFieldColor = editAttributeField.extend({
820
+
821
+ // All events are being listened by iris, and they don't bubble very well,
822
+ // so remove Backbone's listeners.
823
+ events: {},
824
+
825
+ render: function() {
826
+ var self = this;
827
+
828
+ var data = jQuery.extend( {
829
+ id: 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid,
830
+ }, this.model.toJSON() );
831
+
832
+ // Convert meta JSON to attribute string.
833
+ var _meta = [];
834
+ for ( var key in data.meta ) {
835
+
836
+ // Boolean attributes can only require attribute key, not value.
837
+ if ( 'boolean' === typeof( data.meta[ key ] ) ) {
838
+
839
+ // Only set truthy boolean attributes.
840
+ if ( data.meta[ key ] ) {
841
+ _meta.push( _.escape( key ) );
842
+ }
843
+
844
+ } else {
845
+
846
+ _meta.push( _.escape( key ) + '="' + _.escape( data.meta[ key ] ) + '"' );
847
+
848
+ }
849
+
850
+ }
851
+
852
+ data.meta = _meta.join( ' ' );
853
+
854
+ this.$el.html( this.template( data ) );
855
+ this.triggerCallbacks();
856
+
857
+ this.$el.find('input[type="text"]:not(.wp-color-picker)').wpColorPicker({
858
+ change: function(e, ui) {
859
+ self.setValue( $(this).wpColorPicker('color') );
860
+ self.triggerCallbacks();
861
+ }
862
+ });
863
+
864
+ return this;
865
+ }
866
+
867
+ });
868
+
869
+
870
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
871
+ },{"./../utils/sui.js":9,"./edit-attribute-field.js":13}],12:[function(require,module,exports){
872
+ ( function( $ ) {
873
+
874
+ var sui = window.Shortcode_UI;
875
+
876
+ // Cached Data.
877
+ var postSelectCache = {};
878
+
879
+ sui.views.editAttributeFieldPostSelect = sui.views.editAttributeField.extend( {
880
+
881
+ events: {
882
+ 'change .shortcode-ui-post-select': 'inputChanged',
883
+ },
884
+
885
+ inputChanged: function(e) {
886
+ this.setValue( e.val );
887
+ this.triggerCallbacks();
888
+ },
889
+
890
+ render: function() {
891
+
892
+ var self = this,
893
+ defaults = { multiple: false };
894
+
895
+ for ( var arg in defaults ) {
896
+ if ( ! this.model.get( arg ) ) {
897
+ this.model.set( arg, defaults[ arg ] );
898
+ }
899
+ }
900
+
901
+ var data = this.model.toJSON();
902
+ data.id = 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid;
903
+
904
+ this.$el.html( this.template( data ) );
905
+
906
+ var ajaxData = {
907
+ action : 'shortcode_ui_post_field',
908
+ nonce : shortcodeUiPostFieldData.nonce,
909
+ shortcode : this.shortcode.get( 'shortcode_tag'),
910
+ attr : this.model.get( 'attr' )
911
+ };
912
+
913
+ var $field = this.$el.find( '.shortcode-ui-post-select' );
914
+
915
+ $field.select2({
916
+
917
+ placeholder: "Search",
918
+ multiple: this.model.get( 'multiple' ),
919
+ ajax: {
920
+ url: ajaxurl,
921
+ dataType: 'json',
922
+ quietMillis: 250,
923
+ data: function (term, page) {
924
+ ajaxData.s = term;
925
+ ajaxData.page = page;
926
+ return ajaxData;
927
+ },
928
+ results: function ( response, page ) {
929
+
930
+ if ( ! response.success ) {
931
+ return { results: {}, more: false };
932
+ }
933
+
934
+ // Cache data for quicker rendering later.
935
+ postSelectCache = $.extend( postSelectCache, response.data.posts );
936
+
937
+ var more = ( page * response.data.posts_per_page ) < response.data.found_posts; // whether or not there are more results available
938
+ return { results: response.data.posts, more: more };
939
+
940
+ },
941
+ },
942
+
943
+ /**
944
+ * Initialize Callback
945
+ * Used to set render the initial value.
946
+ * Has to make a request to get the title for the current ID.
947
+ */
948
+ initSelection: function(element, callback) {
949
+
950
+ var ids, parsedData = [], cached;
951
+
952
+ // Convert stored value to array of IDs (int).
953
+ ids = $(element)
954
+ .val()
955
+ .split(',')
956
+ .map( function (str) { return str.trim(); } )
957
+ .map( function (str) { return parseInt( str ); } );
958
+
959
+ if ( ids.length < 1 ) {
960
+ return;
961
+ }
962
+
963
+ // Check if there is already cached data.
964
+ for ( var i = 0; i < ids.length; i++ ) {
965
+ cached = _.find( postSelectCache, _.matches( { id: ids[i] } ) );
966
+ if ( cached ) {
967
+ parsedData.push( cached );
968
+ }
969
+ }
970
+
971
+ // If not multiple - return single value if we have one.
972
+ if ( parsedData.length && ! self.model.get( 'multiple' ) ) {
973
+ callback( parsedData[0] );
974
+ return;
975
+ }
976
+
977
+ var uncachedIds = _.difference( ids, _.pluck( parsedData, 'id' ) );
978
+
979
+ if ( ! uncachedIds.length ) {
980
+
981
+ callback( parsedData );
982
+
983
+ } else {
984
+
985
+ var initAjaxData = jQuery.extend( true, {}, ajaxData );
986
+ initAjaxData.action = 'shortcode_ui_post_field';
987
+ initAjaxData.post__in = uncachedIds;
988
+
989
+ $.get( ajaxurl, initAjaxData ).done( function( response ) {
990
+
991
+ if ( ! response.success ) {
992
+ return { results: {}, more: false };
993
+ }
994
+
995
+ postSelectCache = $.extend( postSelectCache, response.data.posts );
996
+
997
+ // If not multi-select, expects single object, not array of objects.
998
+ if ( ! self.model.get( 'multiple' ) ) {
999
+ callback( response.data.posts[0] );
1000
+ return;
1001
+ }
1002
+
1003
+ // Append new data to cached data.
1004
+ // Sort by original order.
1005
+ parsedData = parsedData
1006
+ .concat( response.data.posts )
1007
+ .sort(function (a, b) {
1008
+ if ( ids.indexOf( a.id ) > ids.indexOf( b.id ) ) return 1;
1009
+ if ( ids.indexOf( a.id ) < ids.indexOf( b.id ) ) return -1;
1010
+ return 0;
1011
+ });
1012
+
1013
+ callback( parsedData );
1014
+ return;
1015
+
1016
+ } );
1017
+
1018
+ }
1019
+
1020
+ },
1021
+
1022
+ } );
1023
+
1024
+ // Make multiple values sortable.
1025
+ if ( this.model.get( 'multiple' ) ) {
1026
+ $field.select2('container').find('ul.select2-choices').sortable({
1027
+ containment: 'parent',
1028
+ start: function() { $('.shortcode-ui-post-select').select2('onSortStart'); },
1029
+ update: function() { $('.shortcode-ui-post-select').select2('onSortEnd'); }
1030
+ });
1031
+ }
1032
+
1033
+ return this;
1034
+
1035
+ }
1036
+
1037
+ } );
1038
+
1039
+ /**
1040
+ * Extending SUI Media Controller to hide Select2 UI Drop-Down when menu
1041
+ * changes in Meida modal
1042
+ * 1. going back/forth between different shortcakes (refresh)
1043
+ * 2. changing the menu in left column (deactivate)
1044
+ * 3. @TODO closing the modal.
1045
+ */
1046
+ var mediaController = sui.controllers.MediaController;
1047
+ sui.controllers.MediaController = mediaController.extend({
1048
+
1049
+ refresh: function(){
1050
+ mediaController.prototype.refresh.apply( this, arguments );
1051
+ this.destroySelect2UI();
1052
+ },
1053
+
1054
+ //doesn't need to call parent as it already an "abstract" method in parent to provide callback
1055
+ deactivate: function() {
1056
+ this.destroySelect2UI();
1057
+ },
1058
+
1059
+ destroySelect2UI: function() {
1060
+ $('.shortcode-ui-post-select.select2-container').select2( "close" );
1061
+ }
1062
+
1063
+ });
1064
+
1065
+ } )( jQuery );
1066
+
1067
+ },{}],13:[function(require,module,exports){
1068
  (function (global){
1069
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
1070
  sui = require('./../utils/sui.js'),
1075
  tagName: "div",
1076
 
1077
  events: {
1078
+ 'keyup input[type="text"]': 'inputChanged',
1079
+ 'keyup textarea': 'inputChanged',
1080
+ 'change select': 'inputChanged',
1081
+ 'change input[type=checkbox]': 'inputChanged',
1082
+ 'change input[type=radio]': 'inputChanged',
1083
+ 'change input[type=email]': 'inputChanged',
1084
+ 'change input[type=number]': 'inputChanged',
1085
+ 'change input[type=date]': 'inputChanged',
1086
+ 'change input[type=url]': 'inputChanged',
1087
+ 'input input[type=range]': 'inputChanged',
1088
  },
1089
 
1090
  render: function() {
1116
  data.meta = _meta.join( ' ' );
1117
 
1118
  this.$el.html( this.template( data ) );
1119
+ this.triggerCallbacks();
1120
 
1121
+ return this;
1122
  },
1123
 
1124
  /**
1128
  * then it should update the model. If a callback function is registered
1129
  * for this attribute, it should be called as well.
1130
  */
1131
+ inputChanged: function( e ) {
1132
+
1133
+ var $el;
1134
 
1135
  if ( this.model.get( 'attr' ) ) {
1136
+ $el = this.$el.find( '[name="' + this.model.get( 'attr' ) + '"]' );
1137
  } else {
1138
+ $el = this.$el.find( '[name="inner_content"]' );
1139
  }
1140
 
1141
  if ( 'radio' === this.model.attributes.type ) {
1142
+ this.setValue( $el.filter(':checked').first().val() );
1143
  } else if ( 'checkbox' === this.model.attributes.type ) {
1144
+ this.setValue( $el.is( ':checked' ) );
1145
+ } else if ( 'range' === this.model.attributes.type ) {
1146
+ var rangeId = '#' + e.target.id + '_indicator';
1147
+ var rangeValue = e.target.value;
1148
+ document.querySelector( rangeId ).value = rangeValue;
1149
+ this.setValue( $el.val() );
1150
  } else {
1151
+ this.setValue( $el.val() );
1152
  }
1153
 
1154
+ this.triggerCallbacks();
1155
+ },
1156
+
1157
+ getValue: function() {
1158
+ return this.model.get( 'value' );
1159
+ },
1160
+
1161
+ setValue: function( val ) {
1162
+ this.model.set( 'value', val );
1163
+ },
1164
+
1165
+ triggerCallbacks: function() {
1166
+
1167
  var shortcodeName = this.shortcode.attributes.shortcode_tag,
1168
  attributeName = this.model.get( 'attr' ),
1169
  hookName = [ shortcodeName, attributeName ].join( '.' ),
1188
 
1189
  }
1190
 
1191
+ }, {
1192
+
1193
+ /**
1194
+ * Get an attribute field from a shortcode by name.
1195
+ *
1196
+ * Usage: `sui.views.editAttributeField.getField( collection, 'title')`
1197
+ *
1198
+ * @param array collection of editAttributeFields
1199
+ * @param string attribute name
1200
+ * @return editAttributeField The view corresponding to the matching field
1201
+ */
1202
+ getField: function( collection, attr ) {
1203
+ return _.find( collection,
1204
+ function( viewModel ) {
1205
+ return attr === viewModel.model.get('attr');
1206
+ }
1207
+ );
1208
+ }
1209
+ });
1210
 
1211
  sui.views.editAttributeField = editAttributeField;
1212
  module.exports = editAttributeField;
1213
 
1214
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1215
+ },{"./../utils/sui.js":9}],14:[function(require,module,exports){
1216
  (function (global){
1217
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null),
1218
+ sui = require('./../utils/sui.js'),
1219
+ backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
1220
+ editAttributeField = require('./edit-attribute-field.js'),
1221
+
1222
+ // Additional attribute field types: these fields are all standalone in functionality,
1223
+ // but bundled here for simplicity to save an HTTP request.
1224
+ editAttributeFieldAttachment = require('./edit-attribute-field-attachment.js'),
1225
+ editAttributeFieldPostSelect = require('./edit-attribute-field-post-select.js'),
1226
+ editAttributeFieldColor = require('./edit-attribute-field-color.js');
1227
+
1228
 
1229
  /**
1230
  * Single edit shortcode content view.
1263
  attr_raw: {
1264
  name: attr.get('value')
1265
  }
1266
+ };
1267
 
1268
  var viewObjName = shortcodeUIFieldData[ type ].view;
1269
  var tmplName = shortcodeUIFieldData[ type ].template;
1276
 
1277
  } );
1278
 
1279
+ if ( 0 === this.model.get( 'attrs' ).length && ( ! innerContent || typeof innerContent == 'undefined' ) ) {
1280
  var messageView = new Backbone.View({
1281
  tagName: 'div',
1282
  className: 'notice updated',
1296
  module.exports = EditShortcodeForm;
1297
 
1298
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1299
+ },{"./../utils/sui.js":9,"./edit-attribute-field-attachment.js":10,"./edit-attribute-field-color.js":11,"./edit-attribute-field-post-select.js":12,"./edit-attribute-field.js":13}],15:[function(require,module,exports){
1300
  (function (global){
1301
+ var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null),
1302
+ $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
1303
 
1304
  /**
1305
  * Single shortcode list item view.
1315
  var data = this.model.toJSON();
1316
  this.$el.attr('data-shortcode', data.shortcode_tag);
1317
 
1318
+ if (('listItemImage' in data) && 0 === data.listItemImage.indexOf('dashicons-')) {
1319
+ var fakeEl = $('<div />').addClass( 'dashicons' ).addClass( data.listItemImage );
1320
+ data.listItemImage = $('<div />').append( fakeEl ).html();
 
1321
  }
1322
 
1323
  this.$el.html(this.template(data));
1330
  module.exports = insertShortcodeListItem;
1331
 
1332
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1333
+ },{}],16:[function(require,module,exports){
1334
  (function (global){
1335
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null);
1336
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null);
1349
  },
1350
 
1351
  refresh: function( shortcodeData ) {
1352
+ var options;
1353
  if ( shortcodeData instanceof Backbone.Collection ) {
1354
+ options = { shortcodes: shortcodeData };
1355
  } else {
1356
+ options = { shortcodes: new Shortcodes( shortcodeData ) };
1357
  }
1358
  this.displayShortcodes( options );
1359
  },
1377
  module.exports = insertShortcodeList;
1378
 
1379
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1380
+ },{"./../collections/shortcodes.js":2,"./insert-shortcode-list-item.js":15}],17:[function(require,module,exports){
1381
  (function (global){
1382
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null),
1383
  $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null),
1484
  // @todo - fix this.
1485
  // This is a hack.
1486
  // I just can't work out how to do it properly...
1487
+ if ( view.controller.state().props && view.controller.state().props.get( 'currentShortcode' ) ) {
 
 
 
1488
  window.setTimeout( function() {
1489
  view.controller.$el.addClass( 'hide-menu' );
1490
  } );
1501
  module.exports = mediaFrame;
1502
 
1503
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1504
+ },{"./../controllers/media-controller.js":3,"./media-toolbar":18,"./shortcode-ui":21}],18:[function(require,module,exports){
1505
  (function (global){
1506
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null);
1507
 
1533
  module.exports = Toolbar;
1534
 
1535
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1536
+ },{}],19:[function(require,module,exports){
1537
  (function (global){
1538
  var wp = (typeof window !== "undefined" ? window.wp : typeof global !== "undefined" ? global.wp : null);
1539
  sui = require('./../utils/sui.js');
1569
  },
1570
 
1571
  search: function( event ) {
1572
+ if ( '' === event.target.value ) {
1573
  this.refreshShortcodes( sui.shortcodes );
1574
  } else {
1575
  this.refreshShortcodes( this.controller.search( event.target.value ) );
1579
 
1580
  sui.views.SearchShortcode = SearchShortcode;
1581
  module.exports = SearchShortcode;
1582
+
1583
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1584
+ },{"./../utils/sui.js":9}],20:[function(require,module,exports){
1585
  (function (global){
1586
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
1587
  $ = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
1650
  var isIE = typeof tinymce != 'undefined' ? tinymce.Env.ie : false;
1651
 
1652
  $iframe = $( '<iframe/>', {
1653
+ src: isIE ? 'javascript:""' : '', // jshint ignore:line
1654
  frameBorder: '0',
1655
  allowTransparency: 'true',
1656
  scrolling: 'no',
1753
  var editors = typeof tinymce != 'undefined' ? tinymce.editors : [];
1754
  _.each( editors, function( editor ) {
1755
  _.each( editor.dom.$( 'link[rel="stylesheet"]', editor.getDoc().head ), function( link ) {
1756
+ if ( link.href ) {
1757
+ styles[ link.href ] = true;
1758
+ }
1759
  });
1760
  });
1761
 
1770
  module.exports = ShortcodePreview;
1771
 
1772
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1773
+ },{}],21:[function(require,module,exports){
1774
  (function (global){
1775
  var Backbone = (typeof window !== "undefined" ? window.Backbone : typeof global !== "undefined" ? global.Backbone : null),
1776
  insertShortcodeList = require('./insert-shortcode-list.js'),
 
1777
  ShortcodePreview = require('./shortcode-preview.js'),
1778
  EditShortcodeForm = require('./edit-shortcode-form.js'),
1779
  Toolbar = require('./media-toolbar.js'),
1797
  createToolbar: function(options) {
1798
  toolbarOptions = {
1799
  controller: this.toolbar_controller
1800
+ };
1801
 
1802
  this.toolbar = new Toolbar( toolbarOptions );
1803
 
1837
 
1838
  renderEditShortcodeView: function() {
1839
  var shortcode = this.controller.props.get( 'currentShortcode' );
1840
+ var view = new EditShortcodeForm({ model: shortcode });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1841
  this.$el.append( view.render().el );
1842
 
1843
  if ( this.controller.props.get('action') === 'update' ) {
1876
  module.exports = Shortcode_UI;
1877
 
1878
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1879
+ },{"./../utils/sui.js":9,"./edit-shortcode-form.js":14,"./insert-shortcode-list.js":16,"./media-toolbar.js":18,"./search-shortcode.js":19,"./shortcode-preview.js":20}]},{},[7]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/src/collections/shortcode-attributes.js CHANGED
@@ -11,7 +11,8 @@ var ShortcodeAttributes = Backbone.Collection.extend({
11
  return new this.constructor(_.map(this.models, function(m) {
12
  return m.clone();
13
  }));
14
- }
 
15
  });
16
 
17
  module.exports = ShortcodeAttributes;
11
  return new this.constructor(_.map(this.models, function(m) {
12
  return m.clone();
13
  }));
14
+ },
15
+
16
  });
17
 
18
  module.exports = ShortcodeAttributes;
js/src/field-attachment.js DELETED
@@ -1,152 +0,0 @@
1
- var sui = require('sui-utils/sui'),
2
- editAttributeField = require( 'sui-views/edit-attribute-field' ),
3
- $ = require('jquery');
4
-
5
- // Cache attachment IDs for quicker loading.
6
- var iDCache = {};
7
-
8
- sui.views.editAttributeFieldAttachment = editAttributeField.extend( {
9
-
10
- render: function() {
11
-
12
- var model = this.model;
13
-
14
- // Set model default values.
15
- for ( var arg in ShortcakeImageFieldData.defaultArgs ) {
16
- if ( ! model.get( arg ) ) {
17
- model.set( arg, ShortcakeImageFieldData.defaultArgs[ arg ] );
18
- }
19
- }
20
-
21
- this.$el.html( this.template( model.toJSON() ) );
22
-
23
- var $container = this.$el.find( '.shortcake-attachment-preview' );
24
- var $addButton = $container.find( 'button.add' );
25
- var $removeButton = $container.find( 'button.remove' );
26
-
27
- var frame = wp.media( {
28
- multiple: false,
29
- title: model.get( 'frameTitle' ),
30
- library: {
31
- type: model.get( 'libraryType' ),
32
- },
33
- } );
34
-
35
- /**
36
- * Update the field attachment.
37
- * Re-renders UI.
38
- * If ID is empty - does nothing.
39
- *
40
- * @param {int} id Attachment ID
41
- */
42
- var updateAttachment = function( id ) {
43
-
44
- if ( ! id ) {
45
- return;
46
- }
47
-
48
- model.set( 'value', id );
49
-
50
- if ( iDCache[ id ] ) {
51
- renderPreview( iDCache[ id ] );
52
- return;
53
- }
54
-
55
- $container.addClass( 'loading' );
56
-
57
- wp.ajax.post( 'get-attachment', {
58
- 'id': id
59
- } ).done( function( attachment ) {
60
- // Cache for later.
61
- iDCache[ id ] = attachment;
62
- renderPreview( attachment );
63
- $container.removeClass( 'loading' );
64
- } );
65
-
66
- }
67
-
68
- /**
69
- * Renders attachment preview in field.
70
- * @param {object} attachment model
71
- * @return null
72
- */
73
- var renderPreview = function( attachment ) {
74
-
75
- var $thumbnail = $('<div class="thumbnail"></div>');
76
-
77
- if ( 'image' !== attachment.type ) {
78
-
79
- $( '<img/>', {
80
- src: attachment.icon,
81
- alt: attachment.title,
82
- } ).appendTo( $thumbnail );
83
-
84
- $( '<div/>', {
85
- class: 'filename',
86
- html: '<div>' + attachment.title + '</div>',
87
- } ).appendTo( $thumbnail );
88
-
89
- } else {
90
-
91
- attachmentThumb = (typeof attachment.sizes.thumbnail !== 'undefined') ?
92
- attachment.sizes.thumbnail :
93
- _.first( _.sortBy( attachment.sizes, 'width' ) );
94
-
95
- $( '<img/>', {
96
- src: attachmentThumb.url,
97
- width: attachmentThumb.width,
98
- height: attachmentThumb.height,
99
- alt: attachment.alt,
100
- } ) .appendTo( $thumbnail )
101
-
102
- }
103
-
104
- $thumbnail.find( 'img' ).wrap( '<div class="centered"></div>' );
105
- $container.append( $thumbnail );
106
- $container.toggleClass( 'has-attachment', true );
107
-
108
- }
109
-
110
- /**
111
- * Remove the attachment.
112
- * Render preview & Update the model.
113
- */
114
- var removeAttachment = function() {
115
-
116
- model.set( 'value', null );
117
-
118
- $container.toggleClass( 'has-attachment', false );
119
- $container.toggleClass( 'has-attachment', false );
120
- $container.find( '.thumbnail' ).remove();
121
- }
122
-
123
- // Add initial Attachment if available.
124
- updateAttachment( model.get( 'value' ) );
125
-
126
- // Remove file when the button is clicked.
127
- $removeButton.click( function(e) {
128
- e.preventDefault();
129
- removeAttachment();
130
- });
131
-
132
- // Open media frame when add button is clicked
133
- $addButton.click( function(e) {
134
- e.preventDefault();
135
- frame.open();
136
- } );
137
-
138
- // Update the attachment when an item is selected.
139
- frame.on( 'select', function() {
140
-
141
- var selection = frame.state().get('selection');
142
- attachment = selection.first();
143
-
144
- updateAttachment( attachment.id );
145
-
146
- frame.close();
147
-
148
- });
149
-
150
- }
151
-
152
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/src/field-color.js DELETED
@@ -1,19 +0,0 @@
1
- var sui = require('sui-utils/sui'),
2
- editAttributeField = require( 'sui-views/edit-attribute-field' ),
3
- $ = require('jquery');
4
-
5
- sui.views.editAttributeFieldColor = editAttributeField.extend( {
6
-
7
- render: function() {
8
- this.$el.html( this.template( this.model.toJSON() ) );
9
-
10
- this.$el.find('input[type="text"]:not(.wp-color-picker)').wpColorPicker({
11
- change: function() {
12
- $(this).trigger('keyup');
13
- }
14
- });
15
-
16
- return this;
17
- }
18
-
19
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/src/models/shortcode.js CHANGED
@@ -7,7 +7,7 @@ Shortcode = Backbone.Model.extend({
7
  defaults: {
8
  label: '',
9
  shortcode_tag: '',
10
- attrs: new ShortcodeAttributes,
11
  },
12
 
13
  /**
@@ -77,16 +77,18 @@ Shortcode = Backbone.Model.extend({
77
 
78
  if ( this.get( 'inner_content' ) ) {
79
  content = this.get( 'inner_content' ).get( 'value' );
 
 
80
  }
81
 
82
  if ( attrs.length > 0 ) {
83
- template = "[{{ shortcode }} {{ attributes }}]"
84
  } else {
85
- template = "[{{ shortcode }}]"
86
  }
87
 
88
  if ( content && content.length > 0 ) {
89
- template += "{{ content }}[/{{ shortcode }}]"
90
  }
91
 
92
  template = template.replace( /{{ shortcode }}/g, this.get('shortcode_tag') );
@@ -95,8 +97,7 @@ Shortcode = Backbone.Model.extend({
95
 
96
  return template;
97
 
98
- }
99
-
100
  });
101
 
102
  module.exports = Shortcode;
7
  defaults: {
8
  label: '',
9
  shortcode_tag: '',
10
+ attrs: new ShortcodeAttributes(),
11
  },
12
 
13
  /**
77
 
78
  if ( this.get( 'inner_content' ) ) {
79
  content = this.get( 'inner_content' ).get( 'value' );
80
+ } else if ( this.get( 'inner_content_backup' ) ) {
81
+ content = this.get( 'inner_content_backup' );
82
  }
83
 
84
  if ( attrs.length > 0 ) {
85
+ template = "[{{ shortcode }} {{ attributes }}]";
86
  } else {
87
+ template = "[{{ shortcode }}]";
88
  }
89
 
90
  if ( content && content.length > 0 ) {
91
+ template += "{{ content }}[/{{ shortcode }}]";
92
  }
93
 
94
  template = template.replace( /{{ shortcode }}/g, this.get('shortcode_tag') );
97
 
98
  return template;
99
 
100
+ },
 
101
  });
102
 
103
  module.exports = Shortcode;
js/src/utils/shortcode-view-constructor.js CHANGED
@@ -43,7 +43,7 @@ var shortcodeViewConstructor = {
43
  if ( 'content' in options ) {
44
  var innerContent = shortcodeModel.get('inner_content');
45
  if ( innerContent ) {
46
- innerContent.set('value', options.content)
47
  }
48
  }
49
 
@@ -184,7 +184,11 @@ var shortcodeViewConstructor = {
184
 
185
  if ( matches[3] ) {
186
  var inner_content = currentShortcode.get( 'inner_content' );
187
- inner_content.set( 'value', this.unAutoP( matches[3] ) );
 
 
 
 
188
  }
189
 
190
  return currentShortcode;
@@ -240,7 +244,7 @@ var shortcodeViewConstructor = {
240
  if ('content' in options.shortcode) {
241
  var inner_content = shortcode.get('inner_content');
242
  if ( inner_content ) {
243
- inner_content.set('value', options.shortcode.content)
244
  }
245
  }
246
 
43
  if ( 'content' in options ) {
44
  var innerContent = shortcodeModel.get('inner_content');
45
  if ( innerContent ) {
46
+ innerContent.set('value', options.content);
47
  }
48
  }
49
 
184
 
185
  if ( matches[3] ) {
186
  var inner_content = currentShortcode.get( 'inner_content' );
187
+ if ( inner_content ) {
188
+ inner_content.set( 'value', this.unAutoP( matches[3] ) );
189
+ } else {
190
+ currentShortcode.set( 'inner_content_backup', this.unAutoP( matches[3] ) );
191
+ }
192
  }
193
 
194
  return currentShortcode;
244
  if ('content' in options.shortcode) {
245
  var inner_content = shortcode.get('inner_content');
246
  if ( inner_content ) {
247
+ inner_content.set('value', options.shortcode.content);
248
  }
249
  }
250
 
js/src/utils/sui.js CHANGED
@@ -1,7 +1,7 @@
1
  var Shortcodes = require('sui-collections/shortcodes');
2
 
3
  window.Shortcode_UI = window.Shortcode_UI || {
4
- shortcodes: new Shortcodes,
5
  views: {},
6
  controllers: {},
7
  };
1
  var Shortcodes = require('sui-collections/shortcodes');
2
 
3
  window.Shortcode_UI = window.Shortcode_UI || {
4
+ shortcodes: new Shortcodes(),
5
  views: {},
6
  controllers: {},
7
  };
js/src/views/edit-attribute-field-attachment.js ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var sui = require('sui-utils/sui');
2
+
3
+ var editAttributeFieldAttachment = sui.views.editAttributeField.extend( {
4
+
5
+ events: {
6
+ 'click .add' : '_openMediaFrame',
7
+ 'click .remove' : '_removeAttachment',
8
+ 'click .thumbnail' : '_openMediaFrame',
9
+ 'selectAttachment' : '_selectAttachment',
10
+ },
11
+
12
+ /**
13
+ * Update the field attachment.
14
+ * Re-renders UI.
15
+ * If ID is empty - does nothing.
16
+ *
17
+ * @param {int} id Attachment ID
18
+ */
19
+ updateValue: function( id ) {
20
+
21
+ if ( ! id ) {
22
+ return;
23
+ }
24
+
25
+ this.setValue( id );
26
+
27
+ var self = this;
28
+
29
+ if ( editAttributeFieldAttachment.getFromCache( id ) ) {
30
+ self._renderPreview( editAttributeFieldAttachment.getFromCache( id ) );
31
+
32
+ // Call the updateValue() function, to trigger any listeners
33
+ // hooked on it.
34
+ self.triggerCallbacks();
35
+ return;
36
+ }
37
+
38
+ this.$container.addClass( 'loading' );
39
+
40
+ wp.ajax.post( 'get-attachment', {
41
+ 'id': id
42
+ } ).done( function( attachment ) {
43
+ // Cache for later.
44
+ editAttributeFieldAttachment.setInCache( id, attachment );
45
+ self._renderPreview( attachment );
46
+
47
+ // Call the updateValue() function, to trigger any listeners
48
+ // hooked on it.
49
+ self.triggerCallbacks();
50
+ } ).always( function( attachment ) {
51
+ self.$container.removeClass( 'loading' );
52
+ });
53
+ },
54
+
55
+ render: function() {
56
+
57
+ // Set model default values.
58
+ for ( var arg in ShortcakeImageFieldData.defaultArgs ) {
59
+ if ( ! this.model.get( arg ) ) {
60
+ this.model.set( arg, ShortcakeImageFieldData.defaultArgs[ arg ] );
61
+ }
62
+ }
63
+
64
+ this.$el.html( this.template( this.model.toJSON() ) );
65
+
66
+ this.$container = this.$el.find( '.shortcake-attachment-preview' );
67
+ this.$thumbnailDetailsContainer = this.$el.find( '.thumbnail-details-container' );
68
+ var $addButton = this.$container.find( 'button.add' );
69
+
70
+ this.frame = wp.media( {
71
+ multiple: false,
72
+ title: this.model.get( 'frameTitle' ),
73
+ library: {
74
+ type: this.model.get( 'libraryType' ),
75
+ },
76
+ } );
77
+
78
+ // Add initial Attachment if available.
79
+ this.updateValue( this.model.get( 'value' ) );
80
+
81
+ },
82
+
83
+ /**
84
+ * Renders attachment preview in field.
85
+ * @param {object} attachment model
86
+ * @return null
87
+ */
88
+ _renderPreview: function( attachment ) {
89
+
90
+ var $thumbnail = jQuery('<div class="thumbnail"></div>');
91
+
92
+ if ( 'image' !== attachment.type ) {
93
+
94
+ jQuery( '<img/>', {
95
+ src: attachment.icon,
96
+ alt: attachment.title,
97
+ } ).appendTo( $thumbnail );
98
+
99
+ jQuery( '<div/>', {
100
+ class: 'filename',
101
+ html: '<div>' + attachment.title + '</div>',
102
+ } ).appendTo( $thumbnail );
103
+
104
+ } else {
105
+
106
+ attachmentThumb = (typeof attachment.sizes.thumbnail !== 'undefined') ?
107
+ attachment.sizes.thumbnail :
108
+ _.first( _.sortBy( attachment.sizes, 'width' ) );
109
+
110
+ jQuery( '<img/>', {
111
+ src: attachmentThumb.url,
112
+ width: attachmentThumb.width,
113
+ height: attachmentThumb.height,
114
+ alt: attachment.alt,
115
+ } ) .appendTo( $thumbnail );
116
+
117
+ }
118
+
119
+ $thumbnail.find( 'img' ).wrap( '<div class="centered"></div>' );
120
+ this.$container.append( $thumbnail );
121
+ this.$container.toggleClass( 'has-attachment', true );
122
+
123
+ this.$thumbnailDetailsContainer.find( '.filename' ).text( attachment.filename );
124
+ this.$thumbnailDetailsContainer.find( '.date-formatted' ).text( attachment.dateFormatted );
125
+ this.$thumbnailDetailsContainer.find( '.size' ).text( attachment.filesizeHumanReadable );
126
+ this.$thumbnailDetailsContainer.find( '.dimensions' ).text( attachment.height + ' × ' + attachment.width );
127
+ this.$thumbnailDetailsContainer.find( '.edit-link a' ).attr( "href", attachment.editLink );
128
+ this.$thumbnailDetailsContainer.toggleClass( 'has-attachment', true );
129
+
130
+ },
131
+
132
+ /**
133
+ * Open media frame when add button is clicked.
134
+ *
135
+ */
136
+ _openMediaFrame: function(e) {
137
+ e.preventDefault();
138
+ this.frame.open();
139
+
140
+ var self = this;
141
+ this.frame.on( 'select', function() {
142
+ self.$el.trigger( 'selectAttachment' );
143
+ } );
144
+
145
+ },
146
+
147
+ /**
148
+ * When an attachment is selected from the media frame, update the model value.
149
+ *
150
+ */
151
+ _selectAttachment: function(e) {
152
+ var selection = this.frame.state().get('selection');
153
+ attachment = selection.first();
154
+ if ( attachment.id != this.model.get( 'value' ) ){
155
+ this.model.set( 'value', null );
156
+ this.$container.toggleClass( 'has-attachment', false );
157
+ this.$container.find( '.thumbnail' ).remove();
158
+ this.updateValue( attachment.id );
159
+ }
160
+ this.frame.close();
161
+ },
162
+
163
+ /**
164
+ * Remove the attachment.
165
+ * Render preview & Update the model.
166
+ */
167
+ _removeAttachment: function(e) {
168
+ e.preventDefault();
169
+
170
+ this.model.set( 'value', null );
171
+
172
+ this.$container.toggleClass( 'has-attachment', false );
173
+ this.$container.find( '.thumbnail' ).remove();
174
+ this.$thumbnailDetailsContainer.toggleClass( 'has-attachment', false );
175
+ },
176
+
177
+ }, {
178
+
179
+ _idCache: {},
180
+
181
+ /**
182
+ * Store attachments in a cache for quicker loading.
183
+ */
184
+ setInCache: function( id, attachment ) {
185
+ this._idCache[ id ] = attachment;
186
+ },
187
+
188
+ /**
189
+ * Retrieve an attachment from the cache.
190
+ */
191
+ getFromCache: function( id ){
192
+ if ( 'undefined' === typeof this._idCache[ id ] ) {
193
+ return false;
194
+ }
195
+ return this._idCache[ id ];
196
+ },
197
+
198
+ });
199
+
200
+ module.exports = sui.views.editAttributeFieldAttachment = editAttributeFieldAttachment;
201
+
js/src/views/edit-attribute-field-color.js ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var sui = require('sui-utils/sui'),
2
+ editAttributeField = require( 'sui-views/edit-attribute-field' ),
3
+ $ = require('jquery');
4
+
5
+ sui.views.editAttributeFieldColor = editAttributeField.extend({
6
+
7
+ // All events are being listened by iris, and they don't bubble very well,
8
+ // so remove Backbone's listeners.
9
+ events: {},
10
+
11
+ render: function() {
12
+ var self = this;
13
+
14
+ var data = jQuery.extend( {
15
+ id: 'shortcode-ui-' + this.model.get( 'attr' ) + '-' + this.model.cid,
16
+ }, this.model.toJSON() );
17
+
18
+ // Convert meta JSON to attribute string.
19
+ var _meta = [];
20
+ for ( var key in data.meta ) {
21
+
22
+ // Boolean attributes can only require attribute key, not value.
23
+ if ( 'boolean' === typeof( data.meta[ key ] ) ) {
24
+
25
+ // Only set truthy boolean attributes.
26
+ if ( data.meta[ key ] ) {
27
+ _meta.push( _.escape( key ) );
28
+ }
29
+
30
+ } else {
31
+
32
+ _meta.push( _.escape( key ) + '="' + _.escape( data.meta[ key ] ) + '"' );
33
+
34
+ }
35
+
36
+ }
37
+
38
+ data.meta = _meta.join( ' ' );
39
+
40
+ this.$el.html( this.template( data ) );
41
+ this.triggerCallbacks();
42
+
43
+ this.$el.find('input[type="text"]:not(.wp-color-picker)').wpColorPicker({
44
+ change: function(e, ui) {
45
+ self.setValue( $(this).wpColorPicker('color') );
46
+ self.triggerCallbacks();
47
+ }
48
+ });
49
+
50
+ return this;
51
+ }
52
+
53
+ });
54
+
js/src/{field-post-select.js → views/edit-attribute-field-post-select.js} RENAMED
@@ -8,7 +8,12 @@
8
  sui.views.editAttributeFieldPostSelect = sui.views.editAttributeField.extend( {
9
 
10
  events: {
11
- 'change .shortcode-ui-post-select': 'updateValue',
 
 
 
 
 
12
  },
13
 
14
  render: function() {
@@ -78,7 +83,7 @@
78
  .val()
79
  .split(',')
80
  .map( function (str) { return str.trim(); } )
81
- .map( function (str) { return parseInt( str ); } )
82
 
83
  if ( ids.length < 1 ) {
84
  return;
@@ -86,10 +91,11 @@
86
 
87
  // Check if there is already cached data.
88
  for ( var i = 0; i < ids.length; i++ ) {
89
- if ( cached = _.find( postSelectCache, _.matches( { id: ids[i] } ) ) ) {
 
90
  parsedData.push( cached );
91
  }
92
- };
93
 
94
  // If not multiple - return single value if we have one.
95
  if ( parsedData.length && ! self.model.get( 'multiple' ) ) {
@@ -185,15 +191,4 @@
185
 
186
  });
187
 
188
- /**
189
- * Extending the SUI Tabbed View to hide Select2 UI dropdown when previewing the shortcake
190
- */
191
- var tabbedView = sui.views.TabbedView;
192
- sui.views.TabbedView = tabbedView.extend({
193
- tabSwitcher: function() {
194
- tabbedView.prototype.tabSwitcher.apply( this, arguments );
195
- $('.shortcode-ui-post-select.select2-container').select2( "close" );
196
- }
197
- });
198
-
199
  } )( jQuery );
8
  sui.views.editAttributeFieldPostSelect = sui.views.editAttributeField.extend( {
9
 
10
  events: {
11
+ 'change .shortcode-ui-post-select': 'inputChanged',
12
+ },
13
+
14
+ inputChanged: function(e) {
15
+ this.setValue( e.val );
16
+ this.triggerCallbacks();
17
  },
18
 
19
  render: function() {
83
  .val()
84
  .split(',')
85
  .map( function (str) { return str.trim(); } )
86
+ .map( function (str) { return parseInt( str ); } );
87
 
88
  if ( ids.length < 1 ) {
89
  return;
91
 
92
  // Check if there is already cached data.
93
  for ( var i = 0; i < ids.length; i++ ) {
94
+ cached = _.find( postSelectCache, _.matches( { id: ids[i] } ) );
95
+ if ( cached ) {
96
  parsedData.push( cached );
97
  }
98
+ }
99
 
100
  // If not multiple - return single value if we have one.
101
  if ( parsedData.length && ! self.model.get( 'multiple' ) ) {
191
 
192
  });
193
 
 
 
 
 
 
 
 
 
 
 
 
194
  } )( jQuery );
js/src/views/edit-attribute-field.js CHANGED
@@ -7,15 +7,16 @@ var editAttributeField = Backbone.View.extend( {
7
  tagName: "div",
8
 
9
  events: {
10
- 'keyup input[type="text"]': 'updateValue',
11
- 'keyup textarea': 'updateValue',
12
- 'change select': 'updateValue',
13
- 'change input[type=checkbox]': 'updateValue',
14
- 'change input[type=radio]': 'updateValue',
15
- 'change input[type=email]': 'updateValue',
16
- 'change input[type=number]': 'updateValue',
17
- 'change input[type=date]': 'updateValue',
18
- 'change input[type=url]': 'updateValue',
 
19
  },
20
 
21
  render: function() {
@@ -47,9 +48,9 @@ var editAttributeField = Backbone.View.extend( {
47
  data.meta = _meta.join( ' ' );
48
 
49
  this.$el.html( this.template( data ) );
50
- this.updateValue();
51
 
52
- return this
53
  },
54
 
55
  /**
@@ -59,22 +60,42 @@ var editAttributeField = Backbone.View.extend( {
59
  * then it should update the model. If a callback function is registered
60
  * for this attribute, it should be called as well.
61
  */
62
- updateValue: function( e ) {
 
 
63
 
64
  if ( this.model.get( 'attr' ) ) {
65
- var $el = $( this.el ).find( '[name=' + this.model.get( 'attr' ) + ']' );
66
  } else {
67
- var $el = $( this.el ).find( '[name="inner_content"]' );
68
  }
69
 
70
  if ( 'radio' === this.model.attributes.type ) {
71
- this.model.set( 'value', $el.filter(':checked').first().val() );
72
  } else if ( 'checkbox' === this.model.attributes.type ) {
73
- this.model.set( 'value', $el.is( ':checked' ) );
 
 
 
 
 
74
  } else {
75
- this.model.set( 'value', $el.val() );
76
  }
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  var shortcodeName = this.shortcode.attributes.shortcode_tag,
79
  attributeName = this.model.get( 'attr' ),
80
  hookName = [ shortcodeName, attributeName ].join( '.' ),
@@ -99,7 +120,25 @@ var editAttributeField = Backbone.View.extend( {
99
 
100
  }
101
 
102
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  sui.views.editAttributeField = editAttributeField;
105
  module.exports = editAttributeField;
7
  tagName: "div",
8
 
9
  events: {
10
+ 'keyup input[type="text"]': 'inputChanged',
11
+ 'keyup textarea': 'inputChanged',
12
+ 'change select': 'inputChanged',
13
+ 'change input[type=checkbox]': 'inputChanged',
14
+ 'change input[type=radio]': 'inputChanged',
15
+ 'change input[type=email]': 'inputChanged',
16
+ 'change input[type=number]': 'inputChanged',
17
+ 'change input[type=date]': 'inputChanged',
18
+ 'change input[type=url]': 'inputChanged',
19
+ 'input input[type=range]': 'inputChanged',
20
  },
21
 
22
  render: function() {
48
  data.meta = _meta.join( ' ' );
49
 
50
  this.$el.html( this.template( data ) );
51
+ this.triggerCallbacks();
52
 
53
+ return this;
54
  },
55
 
56
  /**
60
  * then it should update the model. If a callback function is registered
61
  * for this attribute, it should be called as well.
62
  */
63
+ inputChanged: function( e ) {
64
+
65
+ var $el;
66
 
67
  if ( this.model.get( 'attr' ) ) {
68
+ $el = this.$el.find( '[name="' + this.model.get( 'attr' ) + '"]' );
69
  } else {
70
+ $el = this.$el.find( '[name="inner_content"]' );
71
  }
72
 
73
  if ( 'radio' === this.model.attributes.type ) {
74
+ this.setValue( $el.filter(':checked').first().val() );
75
  } else if ( 'checkbox' === this.model.attributes.type ) {
76
+ this.setValue( $el.is( ':checked' ) );
77
+ } else if ( 'range' === this.model.attributes.type ) {
78
+ var rangeId = '#' + e.target.id + '_indicator';
79
+ var rangeValue = e.target.value;
80
+ document.querySelector( rangeId ).value = rangeValue;
81
+ this.setValue( $el.val() );
82
  } else {
83
+ this.setValue( $el.val() );
84
  }
85
 
86
+ this.triggerCallbacks();
87
+ },
88
+
89
+ getValue: function() {
90
+ return this.model.get( 'value' );
91
+ },
92
+
93
+ setValue: function( val ) {
94
+ this.model.set( 'value', val );
95
+ },
96
+
97
+ triggerCallbacks: function() {
98
+
99
  var shortcodeName = this.shortcode.attributes.shortcode_tag,
100
  attributeName = this.model.get( 'attr' ),
101
  hookName = [ shortcodeName, attributeName ].join( '.' ),
120
 
121
  }
122
 
123
+ }, {
124
+
125
+ /**
126
+ * Get an attribute field from a shortcode by name.
127
+ *
128
+ * Usage: `sui.views.editAttributeField.getField( collection, 'title')`
129
+ *
130
+ * @param array collection of editAttributeFields
131
+ * @param string attribute name
132
+ * @return editAttributeField The view corresponding to the matching field
133
+ */
134
+ getField: function( collection, attr ) {
135
+ return _.find( collection,
136
+ function( viewModel ) {
137
+ return attr === viewModel.model.get('attr');
138
+ }
139
+ );
140
+ }
141
+ });
142
 
143
  sui.views.editAttributeField = editAttributeField;
144
  module.exports = editAttributeField;
js/src/views/edit-shortcode-form.js CHANGED
@@ -1,7 +1,14 @@
1
  var wp = require('wp'),
2
- sui = require('sui-utils/sui'),
3
- backbone = require('backbone'),
4
- editAttributeField = require( 'sui-views/edit-attribute-field' );
 
 
 
 
 
 
 
5
 
6
  /**
7
  * Single edit shortcode content view.
@@ -40,7 +47,7 @@ var EditShortcodeForm = wp.Backbone.View.extend({
40
  attr_raw: {
41
  name: attr.get('value')
42
  }
43
- }
44
 
45
  var viewObjName = shortcodeUIFieldData[ type ].view;
46
  var tmplName = shortcodeUIFieldData[ type ].template;
@@ -53,7 +60,7 @@ var EditShortcodeForm = wp.Backbone.View.extend({
53
 
54
  } );
55
 
56
- if ( 0 == this.model.get( 'attrs' ).length && ( ! innerContent || typeof innerContent == 'undefined' ) ) {
57
  var messageView = new Backbone.View({
58
  tagName: 'div',
59
  className: 'notice updated',
1
  var wp = require('wp'),
2
+ sui = require('sui-utils/sui'),
3
+ backbone = require('backbone'),
4
+ editAttributeField = require( 'sui-views/edit-attribute-field' ),
5
+
6
+ // Additional attribute field types: these fields are all standalone in functionality,
7
+ // but bundled here for simplicity to save an HTTP request.
8
+ editAttributeFieldAttachment = require( 'sui-views/edit-attribute-field-attachment' ),
9
+ editAttributeFieldPostSelect = require( 'sui-views/edit-attribute-field-post-select' ),
10
+ editAttributeFieldColor = require( 'sui-views/edit-attribute-field-color' );
11
+
12
 
13
  /**
14
  * Single edit shortcode content view.
47
  attr_raw: {
48
  name: attr.get('value')
49
  }
50
+ };
51
 
52
  var viewObjName = shortcodeUIFieldData[ type ].view;
53
  var tmplName = shortcodeUIFieldData[ type ].template;
60
 
61
  } );
62
 
63
+ if ( 0 === this.model.get( 'attrs' ).length && ( ! innerContent || typeof innerContent == 'undefined' ) ) {
64
  var messageView = new Backbone.View({
65
  tagName: 'div',
66
  className: 'notice updated',
js/src/views/insert-shortcode-list-item.js CHANGED
@@ -1,4 +1,5 @@
1
- var wp = require('wp');
 
2
 
3
  /**
4
  * Single shortcode list item view.
@@ -14,10 +15,9 @@ var insertShortcodeListItem = wp.Backbone.View.extend({
14
  var data = this.model.toJSON();
15
  this.$el.attr('data-shortcode', data.shortcode_tag);
16
 
17
- if (('listItemImage' in data)
18
- && 0 === data.listItemImage.indexOf('dashicons-')) {
19
- data.listItemImage = '<div class="dashicons ' + data.listItemImage
20
- + '"></div>';
21
  }
22
 
23
  this.$el.html(this.template(data));
1
+ var wp = require('wp'),
2
+ $ = require('jquery');
3
 
4
  /**
5
  * Single shortcode list item view.
15
  var data = this.model.toJSON();
16
  this.$el.attr('data-shortcode', data.shortcode_tag);
17
 
18
+ if (('listItemImage' in data) && 0 === data.listItemImage.indexOf('dashicons-')) {
19
+ var fakeEl = $('<div />').addClass( 'dashicons' ).addClass( data.listItemImage );
20
+ data.listItemImage = $('<div />').append( fakeEl ).html();
 
21
  }
22
 
23
  this.$el.html(this.template(data));
js/src/views/insert-shortcode-list.js CHANGED
@@ -15,10 +15,11 @@ var insertShortcodeList = wp.Backbone.View.extend({
15
  },
16
 
17
  refresh: function( shortcodeData ) {
 
18
  if ( shortcodeData instanceof Backbone.Collection ) {
19
- var options = { shortcodes: shortcodeData };
20
  } else {
21
- var options = { shortcodes: new Shortcodes( shortcodeData ) };
22
  }
23
  this.displayShortcodes( options );
24
  },
15
  },
16
 
17
  refresh: function( shortcodeData ) {
18
+ var options;
19
  if ( shortcodeData instanceof Backbone.Collection ) {
20
+ options = { shortcodes: shortcodeData };
21
  } else {
22
+ options = { shortcodes: new Shortcodes( shortcodeData ) };
23
  }
24
  this.displayShortcodes( options );
25
  },
js/src/views/media-frame.js CHANGED
@@ -103,10 +103,7 @@ var mediaFrame = postMediaFrame.extend( {
103
  // @todo - fix this.
104
  // This is a hack.
105
  // I just can't work out how to do it properly...
106
- if (
107
- view.controller.state().props
108
- && view.controller.state().props.get( 'currentShortcode' )
109
- ) {
110
  window.setTimeout( function() {
111
  view.controller.$el.addClass( 'hide-menu' );
112
  } );
103
  // @todo - fix this.
104
  // This is a hack.
105
  // I just can't work out how to do it properly...
106
+ if ( view.controller.state().props && view.controller.state().props.get( 'currentShortcode' ) ) {
 
 
 
107
  window.setTimeout( function() {
108
  view.controller.$el.addClass( 'hide-menu' );
109
  } );
js/src/views/search-shortcode.js CHANGED
@@ -32,7 +32,7 @@ var SearchShortcode = wp.media.view.Search.extend({
32
  },
33
 
34
  search: function( event ) {
35
- if ( event.target.value == '' ) {
36
  this.refreshShortcodes( sui.shortcodes );
37
  } else {
38
  this.refreshShortcodes( this.controller.search( event.target.value ) );
@@ -41,4 +41,4 @@ var SearchShortcode = wp.media.view.Search.extend({
41
  });
42
 
43
  sui.views.SearchShortcode = SearchShortcode;
44
- module.exports = SearchShortcode;
32
  },
33
 
34
  search: function( event ) {
35
+ if ( '' === event.target.value ) {
36
  this.refreshShortcodes( sui.shortcodes );
37
  } else {
38
  this.refreshShortcodes( this.controller.search( event.target.value ) );
41
  });
42
 
43
  sui.views.SearchShortcode = SearchShortcode;
44
+ module.exports = SearchShortcode;
js/src/views/shortcode-preview.js CHANGED
@@ -65,7 +65,7 @@ var ShortcodePreview = Backbone.View.extend({
65
  var isIE = typeof tinymce != 'undefined' ? tinymce.Env.ie : false;
66
 
67
  $iframe = $( '<iframe/>', {
68
- src: isIE ? 'javascript:""' : '',
69
  frameBorder: '0',
70
  allowTransparency: 'true',
71
  scrolling: 'no',
@@ -168,8 +168,9 @@ var ShortcodePreview = Backbone.View.extend({
168
  var editors = typeof tinymce != 'undefined' ? tinymce.editors : [];
169
  _.each( editors, function( editor ) {
170
  _.each( editor.dom.$( 'link[rel="stylesheet"]', editor.getDoc().head ), function( link ) {
171
- var href;
172
- ( href = link.href ) && ( styles[href] = true ); // Poor man's de-duping.
 
173
  });
174
  });
175
 
65
  var isIE = typeof tinymce != 'undefined' ? tinymce.Env.ie : false;
66
 
67
  $iframe = $( '<iframe/>', {
68
+ src: isIE ? 'javascript:""' : '', // jshint ignore:line
69
  frameBorder: '0',
70
  allowTransparency: 'true',
71
  scrolling: 'no',
168
  var editors = typeof tinymce != 'undefined' ? tinymce.editors : [];
169
  _.each( editors, function( editor ) {
170
  _.each( editor.dom.$( 'link[rel="stylesheet"]', editor.getDoc().head ), function( link ) {
171
+ if ( link.href ) {
172
+ styles[ link.href ] = true;
173
+ }
174
  });
175
  });
176
 
js/src/views/shortcode-ui.js CHANGED
@@ -1,6 +1,5 @@
1
  var Backbone = require('backbone'),
2
  insertShortcodeList = require('sui-views/insert-shortcode-list'),
3
- TabbedView = require('sui-views/tabbed-view'),
4
  ShortcodePreview = require('sui-views/shortcode-preview'),
5
  EditShortcodeForm = require('sui-views/edit-shortcode-form'),
6
  Toolbar = require('sui-views/media-toolbar'),
@@ -24,7 +23,7 @@ var Shortcode_UI = Backbone.View.extend({
24
  createToolbar: function(options) {
25
  toolbarOptions = {
26
  controller: this.toolbar_controller
27
- }
28
 
29
  this.toolbar = new Toolbar( toolbarOptions );
30
 
@@ -64,28 +63,7 @@ var Shortcode_UI = Backbone.View.extend({
64
 
65
  renderEditShortcodeView: function() {
66
  var shortcode = this.controller.props.get( 'currentShortcode' );
67
- var view = new TabbedView({
68
- tabs: {
69
- edit: {
70
- label: shortcodeUIData.strings.edit_tab_label,
71
- content: new EditShortcodeForm({ model: shortcode })
72
- },
73
-
74
- preview: {
75
- label: shortcodeUIData.strings.preview_tab_label,
76
- content: new ShortcodePreview({ model: shortcode }),
77
- open: function() {
78
- this.render();
79
- }
80
- }
81
- },
82
-
83
- styles: {
84
- group: 'media-router edit-shortcode-tabs',
85
- tab: 'media-menu-item edit-shortcode-tab'
86
- }
87
- });
88
-
89
  this.$el.append( view.render().el );
90
 
91
  if ( this.controller.props.get('action') === 'update' ) {
1
  var Backbone = require('backbone'),
2
  insertShortcodeList = require('sui-views/insert-shortcode-list'),
 
3
  ShortcodePreview = require('sui-views/shortcode-preview'),
4
  EditShortcodeForm = require('sui-views/edit-shortcode-form'),
5
  Toolbar = require('sui-views/media-toolbar'),
23
  createToolbar: function(options) {
24
  toolbarOptions = {
25
  controller: this.toolbar_controller
26
+ };
27
 
28
  this.toolbar = new Toolbar( toolbarOptions );
29
 
63
 
64
  renderEditShortcodeView: function() {
65
  var shortcode = this.controller.props.get( 'currentShortcode' );
66
+ var view = new EditShortcodeForm({ model: shortcode });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  this.$el.append( view.render().el );
68
 
69
  if ( this.controller.props.get('action') === 'update' ) {
js/src/views/tabbed-view.js DELETED
@@ -1,122 +0,0 @@
1
- var Backbone = require('backbone');
2
- var sui = require('sui-utils/sui');
3
- var $ = require('jquery');
4
-
5
- /**
6
- * Abstraction to manage tabbed content. Tab parameters (e.g., label) along with
7
- * views for associated content are passed to initialize the tabbed view.
8
- *
9
- * @class TabbedView
10
- * @constructor
11
- * @extends Backbone.View
12
- * @params [options]
13
- * @params [options.tabs] {Object} A hash of key:value pairs, where each value
14
- * is itself an object with the following properties:
15
- *
16
- * label: The label to display on the tab. content: The `Backbone.View`
17
- * associated with the tab content.
18
- */
19
- var TabbedView = Backbone.View.extend({
20
- template : wp.template('tabbed-view-base'),
21
- tabs : {},
22
-
23
- events : {
24
- 'click [data-role="tab"]' : function(event) {
25
- this.tabSwitcher(event);
26
- }
27
- },
28
-
29
- initialize : function(options) {
30
- Backbone.View.prototype.initialize.apply(this, arguments);
31
-
32
- _.defaults(this.options = (options || {}), {
33
- styles : {
34
- group : '',
35
- tab : ''
36
- }
37
- });
38
-
39
- this.tabs = _.extend(this.tabs, options.tabs);
40
- },
41
-
42
- /**
43
- * @method render
44
- * @chainable
45
- * @returns {TabbedView}
46
- */
47
- render : function() {
48
- var $content;
49
-
50
- this.$el.html(this.template({
51
- tabs : this.tabs,
52
- styles : this.options.styles
53
- }));
54
-
55
- $content = this.$('[data-role="tab-content"]');
56
- $content.empty();
57
-
58
- _.each(this.tabs, function(tab) {
59
- var $el = tab.content.render().$el;
60
- $el.hide();
61
- $content.append($el);
62
- });
63
-
64
- this.select(0);
65
-
66
- return this;
67
- },
68
-
69
- /**
70
- * Switches tab when previewing or editing
71
- */
72
- tabSwitcher : function(event) {
73
- event.stopPropagation();
74
- event.preventDefault();
75
-
76
- var target = $(event.currentTarget).attr('data-target');
77
-
78
- this.select(target);
79
- },
80
-
81
- /**
82
- * Programmatically select (activate) a specific tab. Used internally to
83
- * process tab click events.
84
- *
85
- * @method select
86
- * @param selector
87
- * {number|string} The index (zero based) or key of the target
88
- * tab.
89
- */
90
- select : function(selector) {
91
- var index = 0;
92
- var target = null;
93
- var tab;
94
-
95
- selector = selector || 0;
96
-
97
- _.each(this.tabs, function(tab, key) {
98
- tab.content.$el.hide();
99
-
100
- if (selector === key || selector === index) {
101
- target = key;
102
- }
103
-
104
- index = index + 1;
105
- });
106
-
107
- this.$('[data-role="tab"]').removeClass('active');
108
-
109
- if (target) {
110
- tab = this.tabs[target];
111
-
112
- this.$('[data-role="tab"][data-target="' + target + '"]').addClass(
113
- 'active');
114
-
115
- tab.content.$el.show();
116
- (typeof tab.open == 'function') && tab.open.call(tab.content);
117
- }
118
- }
119
- });
120
-
121
- sui.views.TabbedView = TabbedView;
122
- module.exports = TabbedView;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/shortcode-ui-pt_BR.mo ADDED
Binary file
languages/shortcode-ui-pt_BR.po ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2015
2
+ # This file is distributed under the same license as the package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: \n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/shortcode-ui\n"
7
+ "POT-Creation-Date: 2015-02-17 17:16:53+00:00\n"
8
+ "PO-Revision-Date: 2015-06-26 20:44-0300\n"
9
+ "Last-Translator: bruno@brunobarros.com <bruno@brunobarros.com>\n"
10
+ "Language-Team: \n"
11
+ "Language: pt_BR\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Generator: Poedit 1.7.3\n"
16
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17
+
18
+ #: inc/class-shortcode-ui.php:86 inc/class-shortcode-ui.php:87
19
+ msgid "Insert Post Element"
20
+ msgstr "Inserir elemento"
21
+
22
+ #: inc/class-shortcode-ui.php:88
23
+ msgid "Post Element Details"
24
+ msgstr "Detalhes do elemento"
25
+
26
+ #: inc/class-shortcode-ui.php:89
27
+ msgid "Insert Element"
28
+ msgstr "Inserir elemento"
29
+
30
+ #: inc/class-shortcode-ui.php:90
31
+ msgid "Update"
32
+ msgstr "Atualizar"
33
+
34
+ #: inc/class-shortcode-ui.php:91
35
+ msgid "Edit"
36
+ msgstr "Editar"
37
+
38
+ #: inc/class-shortcode-ui.php:92
39
+ msgid "Preview"
40
+ msgstr "Pré-visualizar"
41
+
42
+ #: inc/class-shortcode-ui.php:93
43
+ msgid "Failed to load preview"
44
+ msgstr "Erro ao carregar a pré-visualização"
45
+
46
+ #: inc/class-shortcode-ui.php:156
47
+ msgid "Something's rotten in the state of Denmark"
48
+ msgstr "Algo está podre no reino da Dinamarca"
49
+
50
+ #: inc/fields/class-field-attachment.php:47
51
+ #: inc/fields/class-field-attachment.php:48
52
+ msgid "Select Attachment"
53
+ msgstr "Escolha o anexo"
54
+
55
+ #: inc/templates/edit-form.tpl.php:3
56
+ msgid "Back to list"
57
+ msgstr "Voltar à lista"
58
+
59
+ #. Plugin Name of the plugin/theme
60
+ msgid "Shortcode UI"
61
+ msgstr "Shortcode UI"
62
+
63
+ #. Description of the plugin/theme
64
+ msgid "User Interface for adding shortcodes."
65
+ msgstr "Interface para adicionar shortcodes"
66
+
67
+ #. Author of the plugin/theme
68
+ msgid "Fusion Engineering and community"
69
+ msgstr "Fusion Engineering e a comunidade"
70
+
71
+ #. Author URI of the plugin/theme
72
+ msgid "http://next.fusion.net/tag/shortcode-ui/"
73
+ msgstr "http://next.fusion.net/tag/shortcode-ui/"
languages/shortcode-ui-ru_RU.mo ADDED
Binary file
languages/shortcode-ui-ru_RU.po ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2015 Fusion Engineering and community
2
+ # This file is distributed under the GPL v2 or later.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Shortcode UI 0.4.0-alpha\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/shortcode-ui\n"
7
+ "POT-Creation-Date: 2015-07-02 14:13+0300\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2015-07-02 14:19+0300\n"
12
+ "Last-Translator: Sergey Sedykh <sergey@ukstudio.ru>\n"
13
+ "Language-Team: \n"
14
+ "X-Generator: Poedit 1.8.1\n"
15
+ "X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c\n"
16
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
17
+ "X-Poedit-SourceCharset: UTF-8\n"
18
+ "X-Poedit-Basepath: ../\n"
19
+ "X-Textdomain-Support: yes\n"
20
+ "Language: ru_RU\n"
21
+ "X-Poedit-SearchPath-0: .\n"
22
+
23
+ #: inc/class-shortcode-ui.php:40
24
+ msgid "Inner Content"
25
+ msgstr "Внутреннее содержание"
26
+
27
+ #: inc/class-shortcode-ui.php:109 inc/class-shortcode-ui.php:110
28
+ msgid "Insert Post Element"
29
+ msgstr "Добавить блок"
30
+
31
+ #: inc/class-shortcode-ui.php:111
32
+ msgid "%s Details"
33
+ msgstr "%s"
34
+
35
+ #: inc/class-shortcode-ui.php:112
36
+ msgid "Insert Element"
37
+ msgstr "Вставить блок в запись"
38
+
39
+ #: inc/class-shortcode-ui.php:113
40
+ msgid "Update"
41
+ msgstr "Обновить"
42
+
43
+ #: inc/class-shortcode-ui.php:114
44
+ msgid "There are no attributes to configure for this Post Element."
45
+ msgstr "У данного элемента настроек нет."
46
+
47
+ #: inc/class-shortcode-ui.php:115
48
+ msgid "Edit"
49
+ msgstr "Редактировать"
50
+
51
+ #: inc/class-shortcode-ui.php:116
52
+ msgid "Preview"
53
+ msgstr "Предпросмотр"
54
+
55
+ #: inc/class-shortcode-ui.php:117
56
+ msgid "Failed to load preview"
57
+ msgstr "Невозможно загрузить предпросмотр"
58
+
59
+ #: inc/class-shortcode-ui.php:118
60
+ msgid "Search"
61
+ msgstr "Искать"
62
+
63
+ #: inc/class-shortcode-ui.php:119
64
+ msgid "Insert Content"
65
+ msgstr "Добавить содержимое"
66
+
67
+ #: inc/class-shortcode-ui.php:213
68
+ msgid "Something's rotten in the state of Denmark"
69
+ msgstr "Подгнило что-то в Датском государстве"
70
+
71
+ #: inc/fields/class-field-attachment.php:47
72
+ #: inc/fields/class-field-attachment.php:48
73
+ msgid "Select Attachment"
74
+ msgstr "Выберите изображение"
75
+
76
+ #: inc/templates/edit-form.tpl.php:3
77
+ msgid "Back to list"
78
+ msgstr "Назад к списку"
79
+
80
+ #. Plugin Name of the plugin/theme
81
+ msgid "Shortcode UI"
82
+ msgstr "Shortcode UI"
83
+
84
+ #. Description of the plugin/theme
85
+ msgid "User Interface for adding shortcodes."
86
+ msgstr "Интерфейс для добавления шорткодов."
87
+
88
+ #. Author of the plugin/theme
89
+ msgid "Fusion Engineering and community"
90
+ msgstr "Fusion Engineering и сообщество"
91
+
92
+ #. Author URI of the plugin/theme
93
+ msgid "http://next.fusion.net/tag/shortcode-ui/"
94
+ msgstr "http://next.fusion.net/tag/shortcode-ui/"
languages/shortcode-ui.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the GPL v2 or later.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Shortcode UI 0.4.0-alpha\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/shortcode-ui\n"
7
- "POT-Creation-Date: 2015-06-22 19:53:12+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -24,65 +24,69 @@ msgstr ""
24
  "X-Poedit-Bookmarks: \n"
25
  "X-Textdomain-Support: yes\n"
26
 
27
- #: inc/class-shortcode-ui.php:40
28
  msgid "Inner Content"
29
  msgstr ""
30
 
31
- #: inc/class-shortcode-ui.php:109 inc/class-shortcode-ui.php:110
32
  msgid "Insert Post Element"
33
  msgstr ""
34
 
35
- #: inc/class-shortcode-ui.php:111
36
  msgid "%s Details"
37
  msgstr ""
38
 
39
- #: inc/class-shortcode-ui.php:112
40
  msgid "Insert Element"
41
  msgstr ""
42
 
43
- #: inc/class-shortcode-ui.php:113
44
  msgid "Update"
45
  msgstr ""
46
 
47
- #: inc/class-shortcode-ui.php:114
48
  msgid "There are no attributes to configure for this Post Element."
49
  msgstr ""
50
 
51
- #: inc/class-shortcode-ui.php:115
52
  msgid "Edit"
53
  msgstr ""
54
 
55
- #: inc/class-shortcode-ui.php:116
56
- msgid "Preview"
57
- msgstr ""
58
-
59
- #: inc/class-shortcode-ui.php:117
60
  msgid "Failed to load preview"
61
  msgstr ""
62
 
63
- #: inc/class-shortcode-ui.php:118
64
  msgid "Search"
65
  msgstr ""
66
 
67
- #: inc/class-shortcode-ui.php:119
68
  msgid "Insert Content"
69
  msgstr ""
70
 
71
- #: inc/class-shortcode-ui.php:213
72
  msgid "Something's rotten in the state of Denmark"
73
  msgstr ""
74
 
75
- #: inc/fields/class-field-attachment.php:47
76
- #: inc/fields/class-field-attachment.php:48
77
  msgid "Select Attachment"
78
  msgstr ""
79
 
 
 
 
 
 
 
 
 
80
  #: inc/templates/edit-form.tpl.php:3
81
  msgid "Back to list"
82
  msgstr ""
83
 
84
  #. Plugin Name of the plugin/theme
85
- msgid "Shortcode UI"
86
  msgstr ""
87
 
88
  #. Description of the plugin/theme
2
  # This file is distributed under the GPL v2 or later.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Shortcake (Shortcode UI) 0.5.0-alpha\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/shortcode-ui\n"
7
+ "POT-Creation-Date: 2015-08-26 22:28:38+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
24
  "X-Poedit-Bookmarks: \n"
25
  "X-Textdomain-Support: yes\n"
26
 
27
+ #: inc/class-shortcode-ui.php:109
28
  msgid "Inner Content"
29
  msgstr ""
30
 
31
+ #: inc/class-shortcode-ui.php:200 inc/class-shortcode-ui.php:201
32
  msgid "Insert Post Element"
33
  msgstr ""
34
 
35
+ #: inc/class-shortcode-ui.php:202
36
  msgid "%s Details"
37
  msgstr ""
38
 
39
+ #: inc/class-shortcode-ui.php:203
40
  msgid "Insert Element"
41
  msgstr ""
42
 
43
+ #: inc/class-shortcode-ui.php:204
44
  msgid "Update"
45
  msgstr ""
46
 
47
+ #: inc/class-shortcode-ui.php:205
48
  msgid "There are no attributes to configure for this Post Element."
49
  msgstr ""
50
 
51
+ #: inc/class-shortcode-ui.php:206
52
  msgid "Edit"
53
  msgstr ""
54
 
55
+ #: inc/class-shortcode-ui.php:207
 
 
 
 
56
  msgid "Failed to load preview"
57
  msgstr ""
58
 
59
+ #: inc/class-shortcode-ui.php:208
60
  msgid "Search"
61
  msgstr ""
62
 
63
+ #: inc/class-shortcode-ui.php:209
64
  msgid "Insert Content"
65
  msgstr ""
66
 
67
+ #: inc/class-shortcode-ui.php:312
68
  msgid "Something's rotten in the state of Denmark"
69
  msgstr ""
70
 
71
+ #: inc/fields/class-field-attachment.php:79
72
+ #: inc/fields/class-field-attachment.php:80
73
  msgid "Select Attachment"
74
  msgstr ""
75
 
76
+ #: inc/fields/class-field-attachment.php:104
77
+ msgid "Thumbnail Details"
78
+ msgstr ""
79
+
80
+ #: inc/fields/class-field-attachment.php:109
81
+ msgid "Edit Attachment"
82
+ msgstr ""
83
+
84
  #: inc/templates/edit-form.tpl.php:3
85
  msgid "Back to list"
86
  msgstr ""
87
 
88
  #. Plugin Name of the plugin/theme
89
+ msgid "Shortcake (Shortcode UI)"
90
  msgstr ""
91
 
92
  #. Description of the plugin/theme
package.json CHANGED
@@ -10,7 +10,7 @@
10
  "grunt": "^0.4.5",
11
  "grunt-browserify": "^3.4.0",
12
  "grunt-contrib-jasmine": "^0.8.2",
13
- "grunt-contrib-jshint": "^0.11.0",
14
  "grunt-contrib-watch": "^0.6.1",
15
  "grunt-phpcs": "^0.4.0",
16
  "grunt-sass": "^0.18.0",
10
  "grunt": "^0.4.5",
11
  "grunt-browserify": "^3.4.0",
12
  "grunt-contrib-jasmine": "^0.8.2",
13
+ "grunt-contrib-jshint": "^0.11.2",
14
  "grunt-contrib-watch": "^0.6.1",
15
  "grunt-phpcs": "^0.4.0",
16
  "grunt-sass": "^0.18.0",
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: fusionengineering, mattheu, danielbachhuber, zebulonj, goldenapples, jitendraharpalani, sanchothefat, bfintal, davisshaver
3
  Tags: shortcodes
4
  Requires at least: 4.1
5
- Tested up to: 4.2.1
6
- Stable tag: 0.4.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -44,6 +44,23 @@ We've removed the compatibility shim for the magical `content` attribute. If you
44
 
45
  == Changelog ==
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  = 0.4.0 (June 22, 2015) =
48
  * Using [carldanley/wp-js-hooks](https://github.com/carldanley/WP-JS-Hooks) for a basic API to register JS callbacks on shortcode attributes.
49
  * Attachment field uses a loading indicator when the preview for an attachment is loading.
2
  Contributors: fusionengineering, mattheu, danielbachhuber, zebulonj, goldenapples, jitendraharpalani, sanchothefat, bfintal, davisshaver
3
  Tags: shortcodes
4
  Requires at least: 4.1
5
+ Tested up to: 4.3
6
+ Stable tag: 0.5.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
44
 
45
  == Changelog ==
46
 
47
+ = 0.5.0 (August 26, 2015) =
48
+ * Attachment field: Made it easier to change the attachment by clicking on the thumbnail; added attachment metadata in the field view.
49
+ * Attachment field: Refactored JavaScript to trigger events.
50
+ * Added a `range` input type.
51
+ * Introduced a `register_shortcode_ui` hook for plugins to more safely register UI with.
52
+ * Removed Preview tab to bring Shortcake's user experience closer to Core, in which the inline visual preview is preferred over a separate preview in the media modal.
53
+ * Cleaned up JavaScript using JSHint.
54
+ * Added Russian translation.
55
+ * Added Portuguese translation.
56
+ * Added PHPDoc to all classes.
57
+ * Bug fix: Persists `inner_content` for a shortcode even when UI isn't defined.
58
+ * Bug fix: Hitting esc in a Shortcake view will now close the modal. (Fixed in Core.)
59
+ * Bug fix: Hitting delete when a Shortcake preview is selected in the Visual editor now results in the shortcode being removed. (Fixed in Core.)
60
+ * Bug fix: The Shortcake 'search' function no longer visually conflicts with the shortcode grid at small screen sizes. (Fixed in Core.)
61
+ * Bug fix: Use `get_post_type()` instead of `get_current_screen()->post_type` so context is properly set on the frontend.
62
+ * [Full release notes](http://fusion.net/story/182883/introducing-shortcake-v0-5-0-sugar/)
63
+
64
  = 0.4.0 (June 22, 2015) =
65
  * Using [carldanley/wp-js-hooks](https://github.com/carldanley/WP-JS-Hooks) for a basic API to register JS callbacks on shortcode attributes.
66
  * Attachment field uses a loading indicator when the preview for an attachment is loading.
shortcode-ui.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * Plugin Name: Shortcake (Shortcode UI)
4
- * Version: 0.4.0
5
  * Description: User Interface for adding shortcodes.
6
  * Author: Fusion Engineering and community
7
  * Author URI: http://next.fusion.net/tag/shortcode-ui/
@@ -19,7 +19,7 @@
19
  * GNU General Public License for more details.
20
  */
21
 
22
- define( 'SHORTCODE_UI_VERSION', '0.4.0' );
23
 
24
  require_once dirname( __FILE__ ) . '/inc/class-shortcode-ui.php';
25
  require_once dirname( __FILE__ ) . '/inc/fields/class-shortcode-ui-fields.php';
1
  <?php
2
  /**
3
  * Plugin Name: Shortcake (Shortcode UI)
4
+ * Version: 0.5.0
5
  * Description: User Interface for adding shortcodes.
6
  * Author: Fusion Engineering and community
7
  * Author URI: http://next.fusion.net/tag/shortcode-ui/
19
  * GNU General Public License for more details.
20
  */
21
 
22
+ define( 'SHORTCODE_UI_VERSION', '0.5.0' );
23
 
24
  require_once dirname( __FILE__ ) . '/inc/class-shortcode-ui.php';
25
  require_once dirname( __FILE__ ) . '/inc/fields/class-shortcode-ui-fields.php';