| 270 | function editImage( img ) { |
| 271 | var frame, callback; |
| 272 | |
| 273 | frame = wp.media({ |
| 274 | frame: 'image', |
| 275 | state: 'image-details', |
| 276 | metadata: extractImageData( img ) |
| 277 | } ); |
| 278 | |
| 279 | callback = function( imageData ) { |
| 280 | updateImage( img, imageData ); |
| 281 | editor.focus(); |
| 282 | }; |
| 283 | |
| 284 | frame.state('image-details').on( 'update', callback ); |
| 285 | frame.state('replace-image').on( 'replace', callback ); |
| 286 | frame.on( 'close', function() { |
| 287 | editor.focus(); |
| 288 | editor.selection.select( img ); |
| 289 | editor.nodeChanged(); |
| 290 | }); |
| 291 | |
| 292 | frame.open(); |
| 293 | |
| 294 | } |
| 295 | |
| 296 | function removeImage( node ) { |
| 297 | var wrap; |
| 298 | |
| 299 | if ( node.nodeName === 'DIV' && editor.dom.hasClass( node, 'mceTemp' ) ) { |
| 300 | wrap = node; |
| 301 | } else if ( node.nodeName === 'IMG' || node.nodeName === 'DT' || node.nodeName === 'A' ) { |
| 302 | wrap = editor.dom.getParent( node, 'div.mceTemp' ); |
| 303 | } |
| 304 | |
| 305 | if ( wrap ) { |
| 306 | if ( wrap.nextSibling ) { |
| 307 | editor.selection.select( wrap.nextSibling ); |
| 308 | } else if ( wrap.previousSibling ) { |
| 309 | editor.selection.select( wrap.previousSibling ); |
| 310 | } else { |
| 311 | editor.selection.select( wrap.parentNode ); |
| 312 | } |
| 313 | |
| 314 | editor.selection.collapse( true ); |
| 315 | editor.nodeChanged(); |
| 316 | editor.dom.remove( wrap ); |
| 317 | } else { |
| 318 | editor.dom.remove( node ); |
| 319 | } |
| 320 | |
| 321 | selected = false; |
| 322 | |
| 323 | } |
| 324 | |
| 325 | function addToolbar( img ) { |
| 326 | var position, toolbarHtml, toolbar; |
| 327 | |
| 328 | removeToolbar(); |
| 329 | |
| 330 | // Don't attempt to edit placeholders |
| 331 | if ( editor.dom.hasClass( img, 'mceItem' ) || '1' === editor.dom.getAttrib( img, 'data-mce-placeholder' ) ) { |
| 332 | return; |
| 333 | } |
| 334 | |
| 335 | position = editor.dom.getPos( img, editor.getBody() ); |
| 336 | |
| 337 | toolbarHtml = '<div class="wrapper"><div class="dashicons dashicons-format-image edit"></div> <div class="dashicons dashicons-no-alt remove"></div></div>'; |
| 338 | |
| 339 | toolbar = editor.dom.create( 'div', { |
| 340 | 'id': 'wp-image-toolbar', |
| 341 | 'data-mce-bogus': '1', |
| 342 | 'contenteditable': false |
| 343 | }, toolbarHtml ); |
| 344 | |
| 345 | |
| 346 | editor.getBody().appendChild( toolbar ); |
| 347 | |
| 348 | editor.dom.setStyles( toolbar, { |
| 349 | position: 'absolute', |
| 350 | top: position.y, |
| 351 | left: position.x, |
| 352 | width: img.width |
| 353 | } ); |
| 354 | } |
| 355 | |
| 356 | function removeToolbar() { |
| 357 | var toolbar = editor.dom.get( 'wp-image-toolbar' ); |
| 358 | |
| 359 | if ( toolbar ) { |
| 360 | editor.dom.remove( toolbar ); |
| 361 | } |
| 362 | } |
| 363 | |
302 | | editor.on( 'wpImageFormSubmit', function( e ) { |
303 | | var data = e.imgData.data, |
304 | | imgNode = e.imgData.node, |
305 | | caption = e.imgData.caption, |
306 | | captionId = '', |
307 | | captionAlign = '', |
308 | | captionWidth = '', |
309 | | wrap, parent, node, html, imgId; |
310 | | |
311 | | // Temp image id so we can find the node later |
312 | | data.id = '__wp-temp-img-id'; |
313 | | // Cancel the original callback |
314 | | e.imgData.cancel = true; |
315 | | |
316 | | if ( ! data.style ) { |
317 | | data.style = null; |
318 | | } |
319 | | |
320 | | if ( ! data.src ) { |
321 | | // Delete the image and the caption |
322 | | if ( imgNode ) { |
323 | | if ( wrap = dom.getParent( imgNode, 'div.mceTemp' ) ) { |
324 | | dom.remove( wrap ); |
325 | | } else if ( imgNode.parentNode.nodeName === 'A' ) { |
326 | | dom.remove( imgNode.parentNode ); |
327 | | } else { |
328 | | dom.remove( imgNode ); |
329 | | } |
330 | | |
331 | | editor.nodeChanged(); |
332 | | } |
333 | | return; |
334 | | } |
335 | | |
336 | | if ( caption ) { |
337 | | caption = caption.replace( /\r\n|\r/g, '\n' ).replace( /<\/?[a-zA-Z0-9]+( [^<>]+)?>/g, function( a ) { |
338 | | // No line breaks inside HTML tags |
339 | | return a.replace( /[\r\n\t]+/, ' ' ); |
340 | | }); |
341 | | |
342 | | // Convert remaining line breaks to <br> |
343 | | caption = caption.replace( /(<br[^>]*>)\s*\n\s*/g, '$1' ).replace( /\s*\n\s*/g, '<br />' ); |
344 | | } |
345 | | |
346 | | if ( ! imgNode ) { |
347 | | // New image inserted |
348 | | html = dom.createHTML( 'img', data ); |
349 | | |
350 | | if ( caption ) { |
351 | | node = editor.selection.getNode(); |
352 | | |
353 | | if ( data.width ) { |
354 | | captionWidth = parseInt( data.width, 10 ) + 10; |
355 | | captionWidth = ' style="width: '+ captionWidth +'px"'; |
356 | | } |
357 | | |
358 | | html = '<dl class="wp-caption alignnone"' + captionWidth + '>' + |
359 | | '<dt class="wp-caption-dt">'+ html +'</dt><dd class="wp-caption-dd">'+ caption +'</dd></dl>'; |
360 | | |
361 | | if ( node.nodeName === 'P' ) { |
362 | | parent = node; |
363 | | } else { |
364 | | parent = dom.getParent( node, 'p' ); |
365 | | } |
366 | | |
367 | | if ( parent && parent.nodeName === 'P' ) { |
368 | | wrap = dom.create( 'div', { 'class': 'mceTemp', 'draggable': 'true' }, html ); |
369 | | dom.insertAfter( wrap, parent ); |
370 | | editor.selection.select( wrap ); |
371 | | editor.nodeChanged(); |
372 | | |
373 | | if ( dom.isEmpty( parent ) ) { |
374 | | dom.remove( parent ); |
375 | | } |
376 | | } else { |
377 | | editor.selection.setContent( '<div class="mceTemp" draggable="true">' + html + '</div>' ); |
378 | | } |
379 | | } else { |
380 | | editor.selection.setContent( html ); |
381 | | } |
382 | | } else { |
383 | | // Edit existing image |
384 | | |
385 | | // Store the original image id if any |
386 | | imgId = imgNode.id || null; |
387 | | // Update the image node |
388 | | dom.setAttribs( imgNode, data ); |
389 | | wrap = dom.getParent( imgNode, 'dl.wp-caption' ); |
390 | | |
391 | | if ( caption ) { |
392 | | if ( wrap ) { |
393 | | if ( parent = dom.select( 'dd.wp-caption-dd', wrap )[0] ) { |
394 | | parent.innerHTML = caption; |
395 | | } |
396 | | } else { |
397 | | if ( imgNode.className ) { |
398 | | captionId = imgNode.className.match( /wp-image-([0-9]+)/ ); |
399 | | captionAlign = imgNode.className.match( /align(left|right|center|none)/ ); |
400 | | } |
401 | | |
402 | | if ( captionAlign ) { |
403 | | captionAlign = captionAlign[0]; |
404 | | imgNode.className = imgNode.className.replace( /align(left|right|center|none)/g, '' ); |
405 | | } else { |
406 | | captionAlign = 'alignnone'; |
407 | | } |
408 | | |
409 | | captionAlign = ' class="wp-caption ' + captionAlign + '"'; |
410 | | |
411 | | if ( captionId ) { |
412 | | captionId = ' id="attachment_' + captionId[1] + '"'; |
413 | | } |
414 | | |
415 | | captionWidth = data.width || imgNode.clientWidth; |
416 | | |
417 | | if ( captionWidth ) { |
418 | | captionWidth = parseInt( captionWidth, 10 ) + 10; |
419 | | captionWidth = ' style="width: '+ captionWidth +'px"'; |
420 | | } |
421 | | |
422 | | if ( imgNode.parentNode && imgNode.parentNode.nodeName === 'A' ) { |
423 | | html = dom.getOuterHTML( imgNode.parentNode ); |
424 | | node = imgNode.parentNode; |
425 | | } else { |
426 | | html = dom.getOuterHTML( imgNode ); |
427 | | node = imgNode; |
428 | | } |
429 | | |
430 | | html = '<dl ' + captionId + captionAlign + captionWidth + '>' + |
431 | | '<dt class="wp-caption-dt">'+ html +'</dt><dd class="wp-caption-dd">'+ caption +'</dd></dl>'; |
432 | | |
433 | | if ( parent = dom.getParent( imgNode, 'p' ) ) { |
434 | | wrap = dom.create( 'div', { 'class': 'mceTemp', 'draggable': 'true' }, html ); |
435 | | dom.insertAfter( wrap, parent ); |
436 | | editor.selection.select( wrap ); |
437 | | editor.nodeChanged(); |
438 | | |
439 | | // Delete the old image node |
440 | | dom.remove( node ); |
441 | | |
442 | | if ( dom.isEmpty( parent ) ) { |
443 | | dom.remove( parent ); |
444 | | } |
445 | | } else { |
446 | | editor.selection.setContent( '<div class="mceTemp" draggable="true">' + html + '</div>' ); |
447 | | } |
448 | | } |
449 | | } else { |
450 | | if ( wrap ) { |
451 | | // Remove the caption wrapper and place the image in new paragraph |
452 | | if ( imgNode.parentNode.nodeName === 'A' ) { |
453 | | html = dom.getOuterHTML( imgNode.parentNode ); |
454 | | } else { |
455 | | html = dom.getOuterHTML( imgNode ); |
456 | | } |
457 | | |
458 | | parent = dom.create( 'p', {}, html ); |
459 | | dom.insertAfter( parent, wrap.parentNode ); |
460 | | editor.selection.select( parent ); |
461 | | editor.nodeChanged(); |
462 | | dom.remove( wrap.parentNode ); |
463 | | } |
464 | | } |
465 | | } |
466 | | |
467 | | imgNode = dom.get('__wp-temp-img-id'); |
468 | | dom.setAttrib( imgNode, 'id', imgId ); |
469 | | e.imgData.node = imgNode; |
470 | | }); |
471 | | |
472 | | editor.on( 'wpLoadImageData', function( e ) { |
473 | | var parent, |
474 | | data = e.imgData.data, |
475 | | imgNode = e.imgData.node; |
476 | | |
477 | | if ( parent = dom.getParent( imgNode, 'dl.wp-caption' ) ) { |
478 | | parent = dom.select( 'dd.wp-caption-dd', parent )[0]; |
479 | | |
480 | | if ( parent ) { |
481 | | data.caption = editor.serializer.serialize( parent ) |
482 | | .replace( /<br[^>]*>/g, '$&\n' ).replace( /^<p>/, '' ).replace( /<\/p>$/, '' ); |
483 | | } |
484 | | } |
485 | | }); |
486 | | |