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