Insert Pages - Version 2.5

Version Description

  • Maintenance release: prevent infinite loops when using a custom template that doesn't call the_post().
Download this release

Release Info

Developer figureone
Plugin Icon wp plugin Insert Pages
Version 2.5
Comparing to
See all releases

Code changes from version 2.4 to 2.5

css/wpinsertpages.css ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*------------------------------------------------------------------------------
2
+ wp-insertpage (modeled after #wp-link)
3
+ ------------------------------------------------------------------------------*/
4
+
5
+ #wp-insertpage-wrap {
6
+ display: none;
7
+ background-color: #fff;
8
+ -webkit-box-shadow: 0 3px 6px rgba(0,0,0,.3);
9
+ box-shadow: 0 3px 6px rgba(0,0,0,.3);
10
+ width: 500px;
11
+ height: 430px;
12
+ overflow: hidden;
13
+ margin-left: -250px;
14
+ margin-top: -250px;
15
+ position: fixed;
16
+ top: 50%;
17
+ left: 50%;
18
+ z-index: 100105;
19
+ -webkit-transition: height .2s,margin-top .2s;
20
+ transition: height .2s,margin-top .2s;
21
+ }
22
+
23
+ #wp-insertpage-backdrop {
24
+ display: none;
25
+ position: fixed;
26
+ top: 0;
27
+ left: 0;
28
+ right: 0;
29
+ bottom: 0;
30
+ min-height: 360px;
31
+ background: #000;
32
+ opacity: .7;
33
+ filter: alpha(opacity=70);
34
+ z-index: 100100;
35
+ }
36
+
37
+ #wp-insertpage {
38
+ position: relative;
39
+ height: 100%;
40
+ }
41
+
42
+ #wp-insertpage-wrap.options-panel-visible {
43
+ height: 500px;
44
+ margin-top: -250px;
45
+ }
46
+
47
+ #insertpage-modal-title {
48
+ background: #fcfcfc;
49
+ border-bottom: 1px solid #dfdfdf;
50
+ height: 36px;
51
+ font-size: 18px;
52
+ font-weight: 600;
53
+ line-height: 36px;
54
+ padding: 0 36px 0 16px;
55
+ top: 0;
56
+ right: 0;
57
+ left: 0;
58
+ }
59
+
60
+ #wp-insertpage-close {
61
+ color: #666;
62
+ cursor: pointer;
63
+ padding: 0;
64
+ position: absolute;
65
+ top: 0;
66
+ right: 0;
67
+ width: 36px;
68
+ height: 36px;
69
+ text-align: center;
70
+ }
71
+
72
+ #wp-insertpage-close:before {
73
+ font: normal 20px/36px 'dashicons';
74
+ vertical-align: top;
75
+ speak: none;
76
+ -webkit-font-smoothing: antialiased;
77
+ -moz-osx-font-smoothing: grayscale;
78
+ width: 36px;
79
+ height: 36px;
80
+ content: '\f158';
81
+ }
82
+
83
+ #wp-insertpage-close:hover,
84
+ #wp-insertpage-close:focus {
85
+ color: #2ea2cc;
86
+ }
87
+
88
+ #insertpage-selector {
89
+ padding: 0 16px;
90
+ position: absolute;
91
+ top: 36px;
92
+ left: 0;
93
+ right: 0;
94
+ bottom: 44px;
95
+ }
96
+
97
+ #wp-insertpage ol,
98
+ #wp-insertpage ul {
99
+ list-style: none;
100
+ margin: 0;
101
+ padding: 0;
102
+ }
103
+
104
+ #insertpage-options-toggle::after {
105
+ font: normal 20px/1 'dashicons';
106
+ vertical-align: top;
107
+ speak: none;
108
+ -webkit-font-smoothing: antialiased;
109
+ -moz-osx-font-smoothing: grayscale;
110
+ content: '\f140';
111
+ }
112
+
113
+ .options-panel-visible #insertpage-options-toggle::after {
114
+ content: '\f142';
115
+ }
116
+
117
+ #wp-insertpage input[type="text"] {
118
+ -webkit-box-sizing: border-box;
119
+ -moz-box-sizing: border-box;
120
+ box-sizing: border-box;
121
+ }
122
+
123
+ #wp-insertpage #insertpage-options {
124
+ padding: 8px 0 12px;
125
+ }
126
+
127
+ #wp-insertpage p.howto {
128
+ margin: 285px 0 3px;
129
+ }
130
+
131
+ #insertpage-options-toggle {
132
+ cursor: pointer;
133
+ }
134
+
135
+ #insertpage-options-panel .insertpage-format {
136
+ margin-top: 5px;
137
+ white-space: nowrap;
138
+ }
139
+
140
+ #wp-insertpage label input[type="text"] {
141
+ margin-top: 5px;
142
+ width: 77%;
143
+ }
144
+
145
+ #wp-insertpage #insertpage-search-panel label span.search-label {
146
+ display: inline-block;
147
+ width: 80px;
148
+ text-align: right;
149
+ padding-right: 5px;
150
+ max-width: 24%;
151
+ }
152
+
153
+ #wp-insertpage .insertpage-search-field {
154
+ float: left;
155
+ width: 250px;
156
+ max-width: 70%;
157
+ }
158
+
159
+ #wp-insertpage .insertpage-search-wrapper {
160
+ margin: 5px 0 9px;
161
+ display: block;
162
+ overflow: hidden;
163
+ }
164
+
165
+ #wp-insertpage .insertpage-search-wrapper span {
166
+ float: left;
167
+ margin-top: 4px;
168
+ }
169
+
170
+ #wp-insertpage .insertpage-search-wrapper .spinner {
171
+ display: none;
172
+ vertical-align: text-bottom;
173
+ }
174
+
175
+ #wp-insertpage .query-results {
176
+ border: 1px #dfdfdf solid;
177
+ margin: 0;
178
+ background: #fff;
179
+ overflow: auto;
180
+ position: absolute;
181
+ left: 16px;
182
+ right: 16px;
183
+ top: 38px;
184
+ height: 265px;
185
+ }
186
+
187
+ #wp-insertpage li,
188
+ #wp-insertpage .query-notice {
189
+ clear: both;
190
+ margin-bottom: 0;
191
+ border-bottom: 1px solid #f1f1f1;
192
+ color: #333;
193
+ padding: 4px 6px;
194
+ cursor: pointer;
195
+ position: relative;
196
+ }
197
+
198
+ #wp-insertpage li:hover {
199
+ background: #eaf2fa;
200
+ color: #151515;
201
+ }
202
+
203
+ #wp-insertpage li.unselectable {
204
+ border-bottom: 1px solid #dfdfdf;
205
+ }
206
+
207
+ #wp-insertpage li.unselectable:hover {
208
+ background: #fff;
209
+ cursor: auto;
210
+ color: #333;
211
+ }
212
+
213
+ #wp-insertpage li.selected {
214
+ background: #ddd;
215
+ color: #333;
216
+ }
217
+
218
+ #wp-insertpage li.selected .item-title {
219
+ font-weight: bold;
220
+ }
221
+
222
+ #wp-insertpage li:last-child {
223
+ border: none;
224
+ }
225
+
226
+ #wp-insertpage .item-title {
227
+ display: inline-block;
228
+ width: 80%;
229
+ width: -webkit-calc(100% - 68px);
230
+ width: calc(100% - 68px);
231
+ }
232
+
233
+ #wp-insertpage .item-info {
234
+ text-transform: uppercase;
235
+ color: #666;
236
+ font-size: 11px;
237
+ position: absolute;
238
+ right: 5px;
239
+ top: 5px;
240
+ }
241
+
242
+ #wp-insertpage #insertpage-options-panel {
243
+ display: none;
244
+ }
245
+
246
+ #wp-insertpage-wrap.options-panel-visible #insertpage-options-panel {
247
+ display: block;
248
+ }
249
+
250
+ #wp-insertpage .river-waiting {
251
+ display: none;
252
+ padding: 10px 0;
253
+ }
254
+
255
+ #wp-insertpage .river-waiting .spinner {
256
+ margin: 0 auto;
257
+ display: block;
258
+ float: none;
259
+ }
260
+
261
+ #wp-insertpage .submitbox {
262
+ padding: 8px 16px;
263
+ background: #fcfcfc;
264
+ border-top: 1px solid #dfdfdf;
265
+ position: absolute;
266
+ bottom: 0;
267
+ left: 0;
268
+ right: 0;
269
+ }
270
+
271
+ #wp-insertpage-cancel {
272
+ line-height: 25px;
273
+ }
274
+
275
+ #wp-insertpage-update {
276
+ line-height: 23px;
277
+ float: right;
278
+ }
279
+
280
+ #wp-insertpage-submit {
281
+ float: right;
282
+ margin-bottom: 0;
283
+ }
284
+
285
+ @media screen and ( max-width: 782px ) {
286
+ #wp-insertpage-wrap {
287
+ height: 450px;
288
+ margin-top: -250px;
289
+ }
290
+
291
+ #wp-insertpage-wrap.options-panel-visible {
292
+ height: 530px;
293
+ }
294
+
295
+ #wp-insertpage-wrap .query-results {
296
+ top: 48px;
297
+ }
298
+
299
+ #insertpage-selector {
300
+ padding: 0 16px 60px;
301
+ }
302
+
303
+ #wp-insertpage-wrap.options-panel-visible #insertpage-selector {
304
+ bottom: 52px;
305
+ }
306
+
307
+ #wp-insertpage-cancel {
308
+ line-height: 32px;
309
+ }
310
+ }
311
+
312
+ @media screen and ( max-width: 520px ) {
313
+ #wp-insertpage-wrap {
314
+ width: auto;
315
+ margin-left: 0;
316
+ left: 10px;
317
+ right: 10px;
318
+ max-width: 500px;
319
+ }
320
+
321
+ #wp-insertpage-wrap.options-panel-visible {
322
+ height: 550px;
323
+ }
324
+ }
325
+
326
+ @media screen and ( max-height: 520px ) {
327
+ #wp-insertpage-wrap {
328
+ -webkit-transition: none;
329
+ transition: none;
330
+ }
331
+
332
+ #wp-insertpage-wrap,
333
+ #wp-insertpage-wrap.options-panel-visible {
334
+ height: auto;
335
+ margin-top: 0;
336
+ top: 10px;
337
+ bottom: 10px;
338
+ }
339
+
340
+ #insertpage-selector,
341
+ .options-panel-visible #insertpage-selector {
342
+ overflow: auto;
343
+ }
344
+
345
+ #search-panel .query-results,
346
+ .options-panel-visible #search-panel .query-results {
347
+ position: static;
348
+ }
349
+ }
350
+
351
+ @media screen and ( max-height: 290px ) {
352
+ #wp-insertpage-wrap {
353
+ height: auto;
354
+ margin-top: 0;
355
+ top: 10px;
356
+ bottom: 10px;
357
+ }
358
+
359
+ #insertpage-selector {
360
+ overflow: auto;
361
+ height: -webkit-calc(100% - 92px);
362
+ height: calc(100% - 92px);
363
+ padding-bottom: 2px;
364
+ }
365
+
366
+ #search-panel .query-results {
367
+ position: static;
368
+ }
369
+ }
img/insertpages_toolbar_icon-2x.png ADDED
Binary file
img/insertpages_toolbar_icon.png ADDED
Binary file
img/toggle-arrow.png ADDED
Binary file
insert-pages.php CHANGED
@@ -5,7 +5,7 @@ Plugin Name: Insert Pages
5
  Plugin URI: https://bitbucket.org/figureone/insert-pages
6
  Description: Insert Pages lets you embed any WordPress content (e.g., pages, posts, custom post types) into other WordPress content using the Shortcode API.
7
  Author: Paul Ryan
8
- Version: 2.4
9
  Author URI: http://www.linkedin.com/in/paulrryan
10
  License: GPL2
11
  */
@@ -62,7 +62,7 @@ if ( !class_exists( 'InsertPagesPlugin' ) ) {
62
  // Register the TinyMCE toolbar button script
63
  wp_enqueue_script(
64
  'wpinsertpages',
65
- plugins_url( '/assets/js/wpinsertpages.js', __FILE__ ),
66
  array( 'wpdialogs' ),
67
  '20140819'
68
  );
@@ -81,7 +81,7 @@ if ( !class_exists( 'InsertPagesPlugin' ) ) {
81
  // Register the TinyMCE toolbar button styles
82
  wp_enqueue_style(
83
  'wpinsertpagescss',
84
- plugins_url( '/assets/css/wpinsertpages.css', __FILE__ ),
85
  array( 'wp-jquery-ui-dialog' ),
86
  '20140819'
87
  );
@@ -172,8 +172,8 @@ if ( !class_exists( 'InsertPagesPlugin' ) ) {
172
  */
173
  $should_apply_the_content_filter = apply_filters( 'insert_pages_apply_the_content_filter', $should_apply_the_content_filter );
174
 
175
- // Start our new Loop
176
- while ( have_posts() ) {
177
  ob_start(); // Start output buffering so we can save the output to string
178
 
179
  // Show either the title, link, content, everything, or everything via a custom template
@@ -241,7 +241,7 @@ if ( !class_exists( 'InsertPagesPlugin' ) ) {
241
 
242
  // Filter hook: Load the javascript for our custom toolbar button
243
  function insertPages_handleFilter_mceExternalPlugins( $plugins ) {
244
- $plugins['wpInsertPages'] = plugins_url( '/assets/js/wpinsertpages_plugin.js', __FILE__ );
245
  return $plugins;
246
  }
247
 
5
  Plugin URI: https://bitbucket.org/figureone/insert-pages
6
  Description: Insert Pages lets you embed any WordPress content (e.g., pages, posts, custom post types) into other WordPress content using the Shortcode API.
7
  Author: Paul Ryan
8
+ Version: 2.5
9
  Author URI: http://www.linkedin.com/in/paulrryan
10
  License: GPL2
11
  */
62
  // Register the TinyMCE toolbar button script
63
  wp_enqueue_script(
64
  'wpinsertpages',
65
+ plugins_url( '/js/wpinsertpages.js', __FILE__ ),
66
  array( 'wpdialogs' ),
67
  '20140819'
68
  );
81
  // Register the TinyMCE toolbar button styles
82
  wp_enqueue_style(
83
  'wpinsertpagescss',
84
+ plugins_url( '/css/wpinsertpages.css', __FILE__ ),
85
  array( 'wp-jquery-ui-dialog' ),
86
  '20140819'
87
  );
172
  */
173
  $should_apply_the_content_filter = apply_filters( 'insert_pages_apply_the_content_filter', $should_apply_the_content_filter );
174
 
175
+ // Start our new Loop (only iterate once).
176
+ if ( have_posts() ) {
177
  ob_start(); // Start output buffering so we can save the output to string
178
 
179
  // Show either the title, link, content, everything, or everything via a custom template
241
 
242
  // Filter hook: Load the javascript for our custom toolbar button
243
  function insertPages_handleFilter_mceExternalPlugins( $plugins ) {
244
+ $plugins['wpInsertPages'] = plugins_url( '/js/wpinsertpages_plugin.js', __FILE__ );
245
  return $plugins;
246
  }
247
 
js/wpinsertpages.js ADDED
@@ -0,0 +1,583 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Modified from WordPress Advanced Link dialog, wp-includes/js/wplink.js
2
+ /* global ajaxurl, tinymce, wpLinkL10n, setUserSetting, wpActiveEditor */
3
+ var wpInsertPages;
4
+
5
+ (function($){
6
+ var inputs = {}, rivers = {}, editor, searchTimer, RiverInsertPages, QueryInsertPages;
7
+
8
+ wpInsertPages = {
9
+ timeToTriggerRiverInsertPages: 150,
10
+ minRiverInsertPagesAJAXDuration: 200,
11
+ riverBottomThreshold: 5,
12
+ keySensitivity: 100,
13
+ lastSearch: '',
14
+ textarea: '',
15
+
16
+ init : function() {
17
+ inputs.wrap = $( '#wp-insertpage-wrap' );
18
+ inputs.dialog = $( '#wp-insertpage' );
19
+ inputs.backdrop = $( '#wp-insertpage-backdrop' );
20
+ inputs.submit = $('#wp-insertpage-submit' );
21
+ inputs.close = $( '#wp-insertpage-close' );
22
+ // Page info
23
+ inputs.slug = $( '#insertpage-slug-field' );
24
+ inputs.pageID = $( '#insertpage-pageID' );
25
+ inputs.parentPageID = $( '#insertpage-parent-pageID' );
26
+ // Format field (title, link, content, all, choose a custom template ->)
27
+ inputs.format = $( '#insertpage-format-select' );
28
+ // Custom template select field
29
+ inputs.template = $( '#insertpage-template-select' );
30
+ inputs.search = $( '#insertpage-search-field' );
31
+ // Build RiverInsertPagess
32
+ rivers.search = new RiverInsertPages( $( '#insertpage-search-results' ) );
33
+ rivers.recent = new RiverInsertPages( $( '#insertpage-most-recent-results' ) );
34
+ rivers.elements = inputs.dialog.find( '.query-results' );
35
+
36
+ // Bind event handlers
37
+ inputs.dialog.keydown( wpInsertPages.keydown );
38
+ inputs.dialog.keyup( wpInsertPages.keyup );
39
+ inputs.submit.click( function( event ){
40
+ event.preventDefault();
41
+ wpInsertPages.update();
42
+ });
43
+ inputs.close.add( inputs.backdrop ).add( '#wp-insertpage-cancel a' ).click( function( event ) {
44
+ event.preventDefault();
45
+ wpInsertPages.close();
46
+ });
47
+
48
+ $( '#insertpage-options-toggle' ).click( wpInsertPages.toggleInternalLinking );
49
+
50
+ rivers.elements.on('river-select', wpInsertPages.updateFields );
51
+
52
+ inputs.format.change( function() {
53
+ if ( inputs.format.val() == 'template' ) {
54
+ inputs.template.removeAttr( 'disabled' );
55
+ inputs.template.focus();
56
+ } else {
57
+ inputs.template.attr( 'disabled', 'disabled' );
58
+ }
59
+ });
60
+
61
+ inputs.search.keyup( function() {
62
+ var self = this;
63
+
64
+ window.clearTimeout( searchTimer );
65
+ searchTimer = window.setTimeout( function() {
66
+ wpInsertPages.searchInternalLinks.call( self );
67
+ }, 500 );
68
+ });
69
+
70
+ /* for this to work, inputs.slug needs to populate inputs.pageID with id when it changes
71
+ inputs.pageID.change(function() {
72
+ if (inputs.pageID.val() == inputs.parentPageID.val()) { // trying to embed a page in itself
73
+ inputs.submit.attr('disabled','disabled');
74
+ } else {
75
+ inputs.submit.removeAttr('disabled');
76
+ }
77
+ });
78
+ */
79
+ },
80
+
81
+ open: function( editorId ) {
82
+ var ed, node, bookmark, cursorPosition = -1;
83
+
84
+ wpInsertPages.range = null;
85
+
86
+ if ( editorId ) {
87
+ window.wpActiveEditor = editorId;
88
+ }
89
+
90
+ if ( ! window.wpActiveEditor ) {
91
+ return;
92
+ }
93
+
94
+ this.textarea = $( '#' + window.wpActiveEditor ).get( 0 );
95
+
96
+ if ( typeof tinymce !== 'undefined' ) {
97
+ ed = tinymce.get( wpActiveEditor );
98
+
99
+ if ( ed && ! ed.isHidden() ) {
100
+ editor = ed;
101
+
102
+ // Get cursor state (used later to determine if we're in an existing shortcode)
103
+ node = editor.selection.getNode();
104
+ bookmark = editor.selection.getBookmark( 0 );
105
+ cursorPosition = node.innerHTML.indexOf( '<span data-mce-type="bookmark"' );
106
+ editor.selection.moveToBookmark( bookmark );
107
+
108
+ } else {
109
+ editor = null;
110
+ }
111
+
112
+ if ( editor && tinymce.isIE ) {
113
+ editor.windowManager.bookmark = editor.selection.getBookmark();
114
+ }
115
+ }
116
+
117
+ if ( ! wpInsertPages.isMCE() && document.selection ) {
118
+ this.textarea.focus();
119
+ this.range = document.selection.createRange();
120
+ }
121
+
122
+ inputs.wrap.show();
123
+ inputs.backdrop.show();
124
+
125
+ wpInsertPages.refresh( cursorPosition );
126
+ },
127
+
128
+ isMCE: function() {
129
+ return editor && ! editor.isHidden();
130
+ },
131
+
132
+ refresh: function( cursorPosition ) {
133
+ // Refresh rivers (clear links, check visibility)
134
+ rivers.search.refresh();
135
+ rivers.recent.refresh();
136
+
137
+ if ( wpInsertPages.isMCE() )
138
+ wpInsertPages.mceRefresh( cursorPosition );
139
+ else
140
+ wpInsertPages.setDefaultValues();
141
+
142
+ // Focus the Slug field and highlight its contents.
143
+ // If this is moved above the selection changes,
144
+ // IE will show a flashing cursor over the dialog.
145
+ inputs.slug.focus()[0].select();
146
+
147
+ // Load the most recent results if this is the first time opening the panel.
148
+ if ( ! rivers.recent.ul.children().length )
149
+ rivers.recent.ajax();
150
+ },
151
+
152
+ mceRefresh: function( cursorPosition ) {
153
+ var shortcode, bookmark, regexp, match, matches;
154
+
155
+ // Get the existing shortcode the cursor is in (or get the entire node if cursor not in one)
156
+ shortcode = '';
157
+ content = editor.selection.getNode().innerHTML;
158
+ if ( content.indexOf( '[insert page=' ) >= 0 ) {
159
+ // Find occurrences of shortcode in current node and see if the cursor
160
+ // position is inside one of them.
161
+ regexp = /\[insert page=[^\]]*]/g;
162
+ while ( ( match = regexp.exec( content ) ) != null ) {
163
+ startPos = match.index;
164
+ endPos = startPos + match[0].length;
165
+ if ( cursorPosition > startPos && cursorPosition < endPos ) {
166
+ shortcode = match[0];
167
+ break;
168
+ }
169
+ }
170
+ }
171
+
172
+ // If cursor is in a shortcode, set the proper values.
173
+ if ( shortcode.indexOf( '[insert page=' ) == 0 ) {
174
+ // Expand selection to the entire shortcode that the cursor is inside
175
+ range = editor.selection.getRng();
176
+ node = editor.selection.getNode();
177
+ selectedChild = null;
178
+ offset = 0;
179
+ for ( i = 0; i < node.childNodes.length; i++ ) {
180
+ selectedChild = node.childNodes[i];
181
+ length = ( selectedChild.outerHTML ) ? selectedChild.outerHTML.length : selectedChild.textContent.length;
182
+ if ( cursorPosition < offset + length ) {
183
+ break;
184
+ }
185
+ offset += length;
186
+ }
187
+ range.setStart( selectedChild, startPos - offset );
188
+ range.setEnd( selectedChild, endPos - offset );
189
+ editor.selection.setRng( range );
190
+
191
+ // Set slug/id (also set the slug as the search term)
192
+ regexp = /page=['"]([^['"]*)['"]/;
193
+ matches = regexp.exec( shortcode );
194
+ if ( matches.length > 1 ) {
195
+ inputs.slug.val( matches[1] );
196
+ inputs.search.val( matches[1] );
197
+ inputs.search.keyup();
198
+ }
199
+
200
+ regexp = /display=['"]([^['"]*)['"]/;
201
+ matches = regexp.exec( shortcode );
202
+ if ( matches.length > 1 ) {
203
+ if ( matches[1] == 'title' || matches[1] == 'link' || matches[1] == 'content' || matches[1] == 'all' ) {
204
+ inputs.format.val( matches[1] );
205
+ inputs.template.val( 'all' );
206
+ } else {
207
+ inputs.format.val( 'template' );
208
+ inputs.template.val( matches[1] );
209
+ }
210
+ inputs.format.change();
211
+ }
212
+
213
+ // Update save prompt.
214
+ inputs.submit.val( 'Update' );
215
+
216
+ // If there's no link, set the default values.
217
+ } else {
218
+ wpInsertPages.setDefaultValues();
219
+ }
220
+ },
221
+
222
+ setDefaultValues : function() {
223
+ // Set URL and description to defaults.
224
+ // Leave the new tab setting as-is.
225
+ inputs.slug.val('');
226
+ inputs.pageID.val('');
227
+ inputs.format.val('title');
228
+ inputs.format.change();
229
+ inputs.template.val('all');
230
+ inputs.search.val( '' );
231
+ inputs.search.keyup();
232
+ },
233
+
234
+ close: function() {
235
+ if ( ! wpInsertPages.isMCE() ) {
236
+ wpInsertPages.textarea.focus();
237
+
238
+ if ( wpInsertPages.range ) {
239
+ wpInsertPages.range.moveToBookmark( wpInsertPages.range.getBookmark() );
240
+ wpInsertPages.range.select();
241
+ }
242
+ } else {
243
+ editor.focus();
244
+ }
245
+
246
+ inputs.backdrop.hide();
247
+ inputs.wrap.hide();
248
+ },
249
+
250
+ getAttrs: function() {
251
+ return {
252
+ page: inputs.slug.val(),
253
+ pageID: inputs.pageID.val(),
254
+ display: inputs.format.val()=='template' ? inputs.template.val() : inputs.format.val(),
255
+ };
256
+ },
257
+
258
+ update : function() {
259
+ var link,
260
+ attrs = wpInsertPages.getAttrs(),
261
+ b;
262
+
263
+ wpInsertPages.close();
264
+ editor.focus();
265
+
266
+ if ( tinymce.isIE ) {
267
+ editor.selection.moveToBookmark( editor.windowManager.bookmark );
268
+ }
269
+
270
+ // If the values are empty, undo and return
271
+ if ( ! attrs.page || attrs.page == '' ) {
272
+ editor.execCommand("mceBeginUndoLevel");
273
+ b = editor.selection.getBookmark();
274
+ editor.selection.setContent('');
275
+ editor.selection.moveToBookmark(b);
276
+ editor.execCommand("mceEndUndoLevel");
277
+ return;
278
+ }
279
+
280
+ editor.execCommand("mceBeginUndoLevel");
281
+ editor.selection.setContent("[insert " +
282
+ "page='" + attrs.page +"' " +
283
+ "display='" + attrs.display + "'" +
284
+ "]");
285
+ editor.execCommand("mceEndUndoLevel");
286
+ },
287
+
288
+ updateFields : function( e, li, originalEvent ) {
289
+ inputs.slug.val( li.children('.item-slug').val() );
290
+ inputs.pageID.val( li.children('.item-id').val() );
291
+ if ( originalEvent && originalEvent.type == "click" )
292
+ inputs.slug.focus();
293
+ },
294
+
295
+ searchInternalLinks : function() {
296
+ var t = $(this), waiting,
297
+ search = t.val();
298
+
299
+ if ( search.length > 2 ) {
300
+ rivers.recent.hide();
301
+ rivers.search.show();
302
+
303
+ // Don't search if the keypress didn't change the title.
304
+ if ( wpInsertPages.lastSearch == search )
305
+ return;
306
+
307
+ wpInsertPages.lastSearch = search;
308
+ waiting = t.parent().find( '.spinner' ).show();
309
+
310
+ rivers.search.change( search );
311
+ rivers.search.ajax( function() {
312
+ waiting.hide();
313
+ });
314
+ } else {
315
+ rivers.search.hide();
316
+ rivers.recent.show();
317
+ }
318
+ },
319
+
320
+ next : function() {
321
+ rivers.search.next();
322
+ rivers.recent.next();
323
+ },
324
+ prev : function() {
325
+ rivers.search.prev();
326
+ rivers.recent.prev();
327
+ },
328
+
329
+ keydown : function( event ) {
330
+ var fn, key = $.ui.keyCode;
331
+
332
+ switch( event.which ) {
333
+ case key.UP:
334
+ fn = 'prev';
335
+ case key.DOWN:
336
+ fn = fn || 'next';
337
+ clearInterval( wpInsertPages.keyInterval );
338
+ wpInsertPages[ fn ]();
339
+ wpInsertPages.keyInterval = setInterval( wpInsertPages[ fn ], wpInsertPages.keySensitivity );
340
+ break;
341
+ default:
342
+ return;
343
+ }
344
+ event.preventDefault();
345
+ },
346
+ keyup: function( event ) {
347
+ var key = $.ui.keyCode;
348
+
349
+ switch( event.which ) {
350
+ case key.ESCAPE:
351
+ wpInsertPages.cancel();
352
+ break;
353
+ case key.UP:
354
+ case key.DOWN:
355
+ clearInterval( wpInsertPages.keyInterval );
356
+ break;
357
+ default:
358
+ return;
359
+ }
360
+ event.preventDefault();
361
+ },
362
+
363
+ delayedCallback : function( func, delay ) {
364
+ var timeoutTriggered, funcTriggered, funcArgs, funcContext;
365
+
366
+ if ( ! delay )
367
+ return func;
368
+
369
+ setTimeout( function() {
370
+ if ( funcTriggered )
371
+ return func.apply( funcContext, funcArgs );
372
+ // Otherwise, wait.
373
+ timeoutTriggered = true;
374
+ }, delay);
375
+
376
+ return function() {
377
+ if ( timeoutTriggered )
378
+ return func.apply( this, arguments );
379
+ // Otherwise, wait.
380
+ funcArgs = arguments;
381
+ funcContext = this;
382
+ funcTriggered = true;
383
+ };
384
+ },
385
+
386
+ toggleInternalLinking : function( event ) {
387
+ var visible = inputs.wrap.hasClass( 'options-panel-visible');
388
+
389
+ inputs.wrap.toggleClass( 'options-panel-visible', ! visible );
390
+ setUserSetting( 'wpinsertpage', visible ? '0' : '1' );
391
+ inputs[ visible ? 'search' : 'slug' ].focus();
392
+ }
393
+ }
394
+
395
+ RiverInsertPages = function( element, search ) {
396
+ var self = this;
397
+ this.element = element;
398
+ this.ul = element.children( 'ul' );
399
+ this.contentHeight = element.children( '#link-selector-height' );
400
+ this.waiting = element.find('.river-waiting');
401
+
402
+ this.change( search );
403
+ this.refresh();
404
+
405
+ $( '#wp-insertpage .query-results, #wp-insertpage #link-selector' ).scroll( function() {
406
+ self.maybeLoad();
407
+ });
408
+ element.on( 'click', 'li', function( event ) {
409
+ self.select( $( this ), event );
410
+ });
411
+ };
412
+
413
+ $.extend( RiverInsertPages.prototype, {
414
+ refresh: function() {
415
+ this.deselect();
416
+ this.visible = this.element.is(':visible');
417
+ },
418
+ show: function() {
419
+ if ( ! this.visible ) {
420
+ this.deselect();
421
+ this.element.show();
422
+ this.visible = true;
423
+ }
424
+ },
425
+ hide: function() {
426
+ this.element.hide();
427
+ this.visible = false;
428
+ },
429
+ // Selects a list item and triggers the river-select event.
430
+ select: function( li, event ) {
431
+ var liHeight, elHeight, liTop, elTop;
432
+
433
+ if ( li.hasClass('unselectable') || li == this.selected )
434
+ return;
435
+
436
+ this.deselect();
437
+ this.selected = li.addClass('selected');
438
+ // Make sure the element is visible
439
+ liHeight = li.outerHeight();
440
+ elHeight = this.element.height();
441
+ liTop = li.position().top;
442
+ elTop = this.element.scrollTop();
443
+
444
+ if ( liTop < 0 ) // Make first visible element
445
+ this.element.scrollTop( elTop + liTop );
446
+ else if ( liTop + liHeight > elHeight ) // Make last visible element
447
+ this.element.scrollTop( elTop + liTop - elHeight + liHeight );
448
+
449
+ // Trigger the river-select event
450
+ this.element.trigger('river-select', [ li, event, this ]);
451
+ },
452
+ deselect: function() {
453
+ if ( this.selected )
454
+ this.selected.removeClass('selected');
455
+ this.selected = false;
456
+ },
457
+ prev: function() {
458
+ if ( ! this.visible )
459
+ return;
460
+
461
+ var to;
462
+ if ( this.selected ) {
463
+ to = this.selected.prev('li');
464
+ if ( to.length )
465
+ this.select( to );
466
+ }
467
+ },
468
+ next: function() {
469
+ if ( ! this.visible )
470
+ return;
471
+
472
+ var to = this.selected ? this.selected.next('li') : $('li:not(.unselectable):first', this.element);
473
+ if ( to.length )
474
+ this.select( to );
475
+ },
476
+ ajax: function( callback ) {
477
+ var self = this,
478
+ delay = this.query.page == 1 ? 0 : wpInsertPages.minRiverInsertPagesAJAXDuration,
479
+ response = wpInsertPages.delayedCallback( function( results, params ) {
480
+ self.process( results, params );
481
+ if ( callback )
482
+ callback( results, params );
483
+ }, delay );
484
+
485
+ this.query.ajax( response );
486
+ },
487
+ change: function( search ) {
488
+ if ( this.query && this._search == search )
489
+ return;
490
+
491
+ this._search = search;
492
+ this.query = new QueryInsertPages( search );
493
+ this.element.scrollTop(0);
494
+ },
495
+ process: function( results, params ) {
496
+ var list = '', alt = true, classes = '',
497
+ firstPage = params.page == 1;
498
+
499
+ if ( !results ) {
500
+ if ( firstPage ) {
501
+ list += '<li class="unselectable"><span class="item-title"><em>'
502
+ + wpInsertPagesL10n.noMatchesFound
503
+ + '</em></span></li>';
504
+ }
505
+ } else {
506
+ $.each( results, function() {
507
+ classes = alt ? 'alternate' : '';
508
+ classes += this['title'] ? '' : ' no-title';
509
+ list += classes ? '<li class="' + classes + '">' : '<li>';
510
+ list += '<input type="hidden" class="item-permalink" value="' + this['permalink'] + '" />';
511
+ list += '<input type="hidden" class="item-slug" value="' + this['slug'] + '" />';
512
+ list += '<input type="hidden" class="item-id" value="' + this['ID'] + '" />';
513
+ list += '<span class="item-title">';
514
+ list += this['title'] ? this['title'] : wpInsertPagesL10n.noTitle;
515
+ list += '</span><span class="item-info">' + this['info'] + '</span></li>';
516
+ alt = ! alt;
517
+ });
518
+ }
519
+
520
+ this.ul[ firstPage ? 'html' : 'append' ]( list );
521
+ },
522
+ maybeLoad: function() {
523
+ var self = this,
524
+ el = this.element,
525
+ bottom = el.scrollTop() + el.height();
526
+
527
+ if ( ! this.query.ready() || bottom < this.ul.height() - wpInsertPages.riverBottomThreshold )
528
+ return;
529
+
530
+ setTimeout(function() {
531
+ var newTop = el.scrollTop(),
532
+ newBottom = newTop + el.height();
533
+
534
+ if ( ! self.query.ready() || newBottom < self.ul.height() - wpInsertPages.riverBottomThreshold )
535
+ return;
536
+
537
+ self.waiting.show();
538
+ el.scrollTop( newTop + self.waiting.outerHeight() );
539
+
540
+ self.ajax( function() {
541
+ self.waiting.hide();
542
+ });
543
+ }, wpInsertPages.timeToTriggerRiverInsertPages );
544
+ }
545
+ });
546
+
547
+ QueryInsertPages = function( search ) {
548
+ this.page = 1;
549
+ this.allLoaded = false;
550
+ this.querying = false;
551
+ this.search = search;
552
+ };
553
+
554
+ $.extend( QueryInsertPages.prototype, {
555
+ ready: function() {
556
+ return !( this.querying || this.allLoaded );
557
+ },
558
+ ajax: function( callback ) {
559
+ var self = this,
560
+ query = {
561
+ //action : 'wp-insertpage-ajax',
562
+ action : 'insertpage',
563
+ page : this.page,
564
+ '_ajax_inserting_nonce' : $('#_ajax_inserting_nonce').val()
565
+ };
566
+
567
+ if ( this.search )
568
+ query.search = this.search;
569
+
570
+ query.pageID = inputs.pageID.val();
571
+
572
+ this.querying = true;
573
+ $.post( ajaxurl, query, function(r) {
574
+ self.page++;
575
+ self.querying = false;
576
+ self.allLoaded = !r;
577
+ callback( r, query );
578
+ }, "json" );
579
+ }
580
+ });
581
+
582
+ $(document).ready( wpInsertPages.init );
583
+ })(jQuery);
js/wpinsertpages_plugin.js ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function() { // Start a new namespace to avoid collisions
2
+
3
+ function isRetinaDisplay() {
4
+ if (window.matchMedia) {
5
+ var mq = window.matchMedia("only screen and (-moz-min-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 2.6/2), only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (min-device-pixel-ratio: 1.3), only screen and (min-resolution: 1.3dppx)");
6
+ if (mq && mq.matches || (window.devicePixelRatio > 1)) {
7
+ return true;
8
+ } else {
9
+ return false;
10
+ }
11
+ }
12
+ }
13
+
14
+ tinymce.PluginManager.add( 'wpInsertPages', function( editor, url ) {
15
+ var insertPagesButton;
16
+
17
+ // Register a command so that it can be invoked by using tinyMCE.activeEditor.execCommand( 'WP_InsertPages' );
18
+ editor.addCommand( 'WP_InsertPages', function() {
19
+ if ( ( ! insertPagesButton || ! insertPagesButton.disabled() ) && typeof window.wpInsertPages !== 'undefined' ) {
20
+ window.wpInsertPages.open( editor.id );
21
+ }
22
+ })
23
+
24
+ function setState( button, node ) {
25
+ var parentIsShortcode = false,
26
+ bookmark, cursorPosition, regexp, match, startPos, endPos,
27
+ parentIsAnchor = editor.dom.getParent( node, 'a' ),
28
+ parentIsImg = editor.dom.getParent( node, 'img' );
29
+
30
+ // Get whether cursor is in an existing shortcode
31
+ content = node.innerHTML;
32
+ if ( content.indexOf( '[insert page=' ) >= 0 ) {
33
+ // Find the cursor position in the current node.
34
+ bookmark = editor.selection.getBookmark( 0 );
35
+ cursorPosition = node.innerHTML.indexOf( '<span data-mce-type="bookmark"' );
36
+ editor.selection.moveToBookmark( bookmark );
37
+
38
+ // Find occurrences of shortcode in current node and see if the cursor
39
+ // position is inside one of them.
40
+ regexp = /\[insert page=[^\]]*]/g;
41
+ while ( ( match = regexp.exec( content ) ) != null ) {
42
+ startPos = match.index;
43
+ endPos = startPos + match[0].length;
44
+ if ( cursorPosition > startPos && cursorPosition < endPos ) {
45
+ parentIsShortcode = true;
46
+ break;
47
+ }
48
+ }
49
+ }
50
+
51
+ button.disabled( parentIsAnchor || parentIsImg );
52
+ button.active( parentIsShortcode );
53
+ }
54
+
55
+ editor.addButton( 'wpInsertPages_button', {
56
+ image: url + '/../img/insertpages_toolbar_icon' + ( isRetinaDisplay() ? '-2x' : '' ) + '.png',
57
+ tooltip: 'Insert page',
58
+ cmd: 'WP_InsertPages',
59
+
60
+ onPostRender: function() {
61
+ insertPagesButton = this;
62
+
63
+ editor.on( 'nodechange', function( event ) {
64
+ setState( insertPagesButton, event.element );
65
+ });
66
+ }
67
+ });
68
+ })
69
+
70
+ } )();
readme.txt CHANGED
@@ -86,6 +86,9 @@ Just one! The plugin prevents you from embedding a page in itself, but you can t
86
 
87
  == Changelog ==
88
 
 
 
 
89
  = 2.4 =
90
  * Add insert_pages_apply_nesting_check filter. Use it to disable the deep nesting check which prevents inserted pages from being embedded within other inserted pages. Example usage:
91
  `function theme_init() {
86
 
87
  == Changelog ==
88
 
89
+ = 2.5 =
90
+ * Maintenance release: prevent infinite loops when using a custom template that doesn't call the_post().
91
+
92
  = 2.4 =
93
  * Add insert_pages_apply_nesting_check filter. Use it to disable the deep nesting check which prevents inserted pages from being embedded within other inserted pages. Example usage:
94
  `function theme_init() {