wp/wp-admin/js/image-edit.js
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
   141 	 * @param {number} postid The post ID.
   141 	 * @param {number} postid The post ID.
   142 	 *
   142 	 *
   143 	 * @return {void}
   143 	 * @return {void}
   144 	 */
   144 	 */
   145 	init : function(postid) {
   145 	init : function(postid) {
   146 		var t = this, old = $('#image-editor-' + t.postid),
   146 		var t = this, old = $('#image-editor-' + t.postid);
   147 			x = t.intval( $('#imgedit-x-' + postid).val() ),
       
   148 			y = t.intval( $('#imgedit-y-' + postid).val() );
       
   149 
   147 
   150 		if ( t.postid !== postid && old.length ) {
   148 		if ( t.postid !== postid && old.length ) {
   151 			t.close(t.postid);
   149 			t.close(t.postid);
   152 		}
   150 		}
   153 
   151 
   154 		t.hold.w = t.hold.ow = x;
       
   155 		t.hold.h = t.hold.oh = y;
       
   156 		t.hold.xy_ratio = x / y;
       
   157 		t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() );
   152 		t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() );
   158 		t.postid = postid;
   153 		t.postid = postid;
   159 		$('#imgedit-response-' + postid).empty();
   154 		$('#imgedit-response-' + postid).empty();
   160 
   155 
   161 		$('#imgedit-panel-' + postid).on( 'keypress', function(e) {
   156 		$('#imgedit-panel-' + postid).on( 'keypress', function(e) {
   184 				return false;
   179 				return false;
   185 			}
   180 			}
   186 		});
   181 		});
   187 
   182 
   188 		$( document ).on( 'image-editor-ui-ready', this.focusManager );
   183 		$( document ).on( 'image-editor-ui-ready', this.focusManager );
       
   184 	},
       
   185 
       
   186 	/**
       
   187 	 * Calculate the image size and save it to memory.
       
   188 	 *
       
   189 	 * @since 6.7.0
       
   190 	 *
       
   191 	 * @memberof imageEdit
       
   192 	 *
       
   193 	 * @param {number} postid The post ID.
       
   194 	 *
       
   195 	 * @return {void}
       
   196 	 */
       
   197 	calculateImgSize: function( postid ) {
       
   198 		var t = this,
       
   199 		x = t.intval( $( '#imgedit-x-' + postid ).val() ),
       
   200 		y = t.intval( $( '#imgedit-y-' + postid ).val() );
       
   201 
       
   202 		t.hold.w = t.hold.ow = x;
       
   203 		t.hold.h = t.hold.oh = y;
       
   204 		t.hold.xy_ratio = x / y;
       
   205 		t.hold.sizer = parseFloat( $( '#imgedit-sizer-' + postid ).val() );
       
   206 		t.currentCropSelection = null;
   189 	},
   207 	},
   190 
   208 
   191 	/**
   209 	/**
   192 	 * Toggles the wait/load icon in the editor.
   210 	 * Toggles the wait/load icon in the editor.
   193 	 *
   211 	 *
   276 
   294 
   277 	/**
   295 	/**
   278 	 * Navigate popup menu by arrow keys.
   296 	 * Navigate popup menu by arrow keys.
   279 	 *
   297 	 *
   280 	 * @since 6.3.0
   298 	 * @since 6.3.0
   281 	 *
   299 	 * @since 6.7.0 Added the event parameter.
   282 	 * @memberof imageEdit
   300 	 *
   283 	 *
   301 	 * @memberof imageEdit
       
   302 	 *
       
   303 	 * @param {Event} event The key or click event.
   284 	 * @param {HTMLElement} el The current element.
   304 	 * @param {HTMLElement} el The current element.
   285 	 *
   305 	 *
   286 	 * @return {boolean} Always returns false.
   306 	 * @return {boolean} Always returns false.
   287 	 */
   307 	 */
   288 	browsePopup : function(el) {
   308 	browsePopup : function(event, el) {
   289 		var $el = $( el );
   309 		var $el = $( el );
   290 		var $collection = $( el ).parent( '.imgedit-popup-menu' ).find( 'button' );
   310 		var $collection = $( el ).parent( '.imgedit-popup-menu' ).find( 'button' );
   291 		var $index = $collection.index( $el );
   311 		var $index = $collection.index( $el );
   292 		var $prev = $index - 1;
   312 		var $prev = $index - 1;
   293 		var $next = $index + 1;
   313 		var $next = $index + 1;
   296 			$prev = $last - 1;
   316 			$prev = $last - 1;
   297 		}
   317 		}
   298 		if ( $next === $last ) {
   318 		if ( $next === $last ) {
   299 			$next = 0;
   319 			$next = 0;
   300 		}
   320 		}
   301 		var $target = false;
   321 		var target = false;
   302 		if ( event.keyCode === 40 ) {
   322 		if ( event.keyCode === 40 ) {
   303 			$target = $collection.get( $next );
   323 			target = $collection.get( $next );
   304 		} else if ( event.keyCode === 38 ) {
   324 		} else if ( event.keyCode === 38 ) {
   305 			$target = $collection.get( $prev );
   325 			target = $collection.get( $prev );
   306 		}
   326 		}
   307 		if ( $target ) {
   327 		if ( target ) {
   308 			$target.focus();
   328 			target.focus();
   309 			event.preventDefault();
   329 			event.preventDefault();
   310 		}
   330 		}
   311 
   331 
   312 		return false;
   332 		return false;
   313 	},
   333 	},
   523 
   543 
   524 			// Filter the last step/action from the history.
   544 			// Filter the last step/action from the history.
   525 			for ( n in history ) {
   545 			for ( n in history ) {
   526 				i = history[n];
   546 				i = history[n];
   527 				if ( i.hasOwnProperty('c') ) {
   547 				if ( i.hasOwnProperty('c') ) {
   528 					op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h } };
   548 					op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h, 'r': i.c.r } };
   529 				} else if ( i.hasOwnProperty('r') ) {
   549 				} else if ( i.hasOwnProperty('r') ) {
   530 					op[n] = { 'r': i.r.r };
   550 					op[n] = { 'r': i.r.r };
   531 				} else if ( i.hasOwnProperty('f') ) {
   551 				} else if ( i.hasOwnProperty('f') ) {
   532 					op[n] = { 'f': i.f.f };
   552 					op[n] = { 'f': i.f.f };
   533 				}
   553 				}
   858 
   878 
   859 		// Ensure init has run even when directly loaded.
   879 		// Ensure init has run even when directly loaded.
   860 		if ( 'undefined' === typeof this.hold.sizer ) {
   880 		if ( 'undefined' === typeof this.hold.sizer ) {
   861 			this.init( postid );
   881 			this.init( postid );
   862 		}
   882 		}
       
   883 		this.calculateImgSize( postid );
   863 
   884 
   864 		this.initCrop(postid, img, parent);
   885 		this.initCrop(postid, img, parent);
   865 		this.setCropSelection( postid, { 'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'width': img.innerWidth(), 'height': img.innerHeight() } );
   886 		this.setCropSelection( postid, { 'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'width': img.innerWidth(), 'height': img.innerHeight() } );
   866 
   887 
   867 		this.toggleEditor( postid, 0, true );
   888 		this.toggleEditor( postid, 0, true );
   907 	 */
   928 	 */
   908 	initCrop : function(postid, image, parent) {
   929 	initCrop : function(postid, image, parent) {
   909 		var t = this,
   930 		var t = this,
   910 			selW = $('#imgedit-sel-width-' + postid),
   931 			selW = $('#imgedit-sel-width-' + postid),
   911 			selH = $('#imgedit-sel-height-' + postid),
   932 			selH = $('#imgedit-sel-height-' + postid),
   912 			selX = $('#imgedit-start-x-' + postid),
       
   913 			selY = $('#imgedit-start-y-' + postid),
       
   914 			$image = $( image ),
   933 			$image = $( image ),
   915 			$img;
   934 			$img;
   916 
   935 
   917 		// Already initialized?
   936 		// Already initialized?
   918 		if ( $image.data( 'imgAreaSelect' ) ) {
   937 		if ( $image.data( 'imgAreaSelect' ) ) {
   943 				/**
   962 				/**
   944 				 * Binds mouse down event to the cropping container.
   963 				 * Binds mouse down event to the cropping container.
   945 				 *
   964 				 *
   946 				 * @return {void}
   965 				 * @return {void}
   947 				 */
   966 				 */
   948 				parent.children().on( 'mousedown, touchstart', function(e){
   967 				parent.children().on( 'mousedown touchstart', function(e) {
   949 					var ratio = false, sel, defRatio;
   968 					var ratio = false,
   950 
   969 					 	sel = t.iasapi.getSelection(),
   951 					if ( e.shiftKey ) {
   970 					 	cx = t.intval( $( '#imgedit-crop-width-' + postid ).val() ),
   952 						sel = t.iasapi.getSelection();
   971 					 	cy = t.intval( $( '#imgedit-crop-height-' + postid ).val() );
   953 						defRatio = t.getSelRatio(postid);
   972 
   954 						ratio = ( sel && sel.width && sel.height ) ? sel.width + ':' + sel.height : defRatio;
   973 					if ( cx && cy ) {
       
   974 						ratio = t.getSelRatio( postid );
       
   975 					} else if ( e.shiftKey && sel && sel.width && sel.height ) {
       
   976 						ratio = sel.width + ':' + sel.height;
   955 					}
   977 					}
   956 
   978 
   957 					t.iasapi.setOptions({
   979 					t.iasapi.setOptions({
   958 						aspectRatio: ratio
   980 						aspectRatio: ratio
   959 					});
   981 					});
   998 			 * @param {Object} c   The selection.
  1020 			 * @param {Object} c   The selection.
   999 			 *
  1021 			 *
  1000 			 * @return {void}
  1022 			 * @return {void}
  1001 			 */
  1023 			 */
  1002 			onSelectChange: function(img, c) {
  1024 			onSelectChange: function(img, c) {
  1003 				var sizer = imageEdit.hold.sizer;
  1025 				var sizer = imageEdit.hold.sizer,
  1004 				selW.val( imageEdit.round(c.width / sizer) );
  1026 					oldSel = imageEdit.currentCropSelection;
  1005 				selH.val( imageEdit.round(c.height / sizer) );
  1027 
  1006 				selX.val( imageEdit.round(c.x1 / sizer) );
  1028 				if ( oldSel != null && oldSel.width == c.width && oldSel.height == c.height ) {
  1007 				selY.val( imageEdit.round(c.y1 / sizer) );
  1029 					return;
       
  1030 				}
       
  1031 
       
  1032 				selW.val( Math.min( imageEdit.hold.w, imageEdit.round( c.width / sizer ) ) );
       
  1033 				selH.val( Math.min( imageEdit.hold.h, imageEdit.round( c.height / sizer ) ) );
       
  1034 
       
  1035 				t.currentCropSelection = c;
  1008 			}
  1036 			}
  1009 		});
  1037 		});
  1010 	},
  1038 	},
  1011 
  1039 
  1012 	/**
  1040 	/**
  1020 	 * @param {Object} c      The selection.
  1048 	 * @param {Object} c      The selection.
  1021 	 *
  1049 	 *
  1022 	 * @return {boolean}
  1050 	 * @return {boolean}
  1023 	 */
  1051 	 */
  1024 	setCropSelection : function(postid, c) {
  1052 	setCropSelection : function(postid, c) {
  1025 		var sel;
  1053 		var sel,
       
  1054 			selW = $( '#imgedit-sel-width-' + postid ),
       
  1055 			selH = $( '#imgedit-sel-height-' + postid ),
       
  1056 			sizer = this.hold.sizer,
       
  1057 			hold = this.hold;
  1026 
  1058 
  1027 		c = c || 0;
  1059 		c = c || 0;
  1028 
  1060 
  1029 		if ( !c || ( c.width < 3 && c.height < 3 ) ) {
  1061 		if ( !c || ( c.width < 3 && c.height < 3 ) ) {
  1030 			this.setDisabled( $( '.imgedit-crop', '#imgedit-panel-' + postid ), 1 );
  1062 			this.setDisabled( $( '.imgedit-crop', '#imgedit-panel-' + postid ), 1 );
  1035 			$('#imgedit-start-y-' + postid).val('0');
  1067 			$('#imgedit-start-y-' + postid).val('0');
  1036 			$('#imgedit-selection-' + postid).val('');
  1068 			$('#imgedit-selection-' + postid).val('');
  1037 			return false;
  1069 			return false;
  1038 		}
  1070 		}
  1039 
  1071 
  1040 		sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height };
  1072 		// adjust the selection within the bounds of the image on 100% scale
       
  1073 		var excessW = hold.w - ( Math.round( c.x1 / sizer ) + parseInt( selW.val() ) );
       
  1074 		var excessH = hold.h - ( Math.round( c.y1 / sizer ) + parseInt( selH.val() ) );
       
  1075 		var x = Math.round( c.x1 / sizer ) + Math.min( 0, excessW );
       
  1076 		var y = Math.round( c.y1 / sizer ) + Math.min( 0, excessH );
       
  1077 
       
  1078 		// use 100% scaling to prevent rounding errors
       
  1079 		sel = { 'r': 1, 'x': x, 'y': y, 'w': selW.val(), 'h': selH.val() };
       
  1080 
  1041 		this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1);
  1081 		this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1);
  1042 		$('#imgedit-selection-' + postid).val( JSON.stringify(sel) );
  1082 		$('#imgedit-selection-' + postid).val( JSON.stringify(sel) );
  1043 	},
  1083 	},
  1044 
  1084 
  1045 
  1085 
  1163 		if ( $(t).hasClass('disabled') ) {
  1203 		if ( $(t).hasClass('disabled') ) {
  1164 			return false;
  1204 			return false;
  1165 		}
  1205 		}
  1166 		this.closePopup(t);
  1206 		this.closePopup(t);
  1167 		this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce);
  1207 		this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce);
       
  1208 
       
  1209 		// Clear the selection fields after rotating.
       
  1210 		$( '#imgedit-sel-width-' + postid ).val( '' );
       
  1211 		$( '#imgedit-sel-height-' + postid ).val( '' );
       
  1212 		this.currentCropSelection = null;
  1168 	},
  1213 	},
  1169 
  1214 
  1170 	/**
  1215 	/**
  1171 	 * Flips the image.
  1216 	 * Flips the image.
  1172 	 *
  1217 	 *
  1185 		if ( $(t).hasClass('disabled') ) {
  1230 		if ( $(t).hasClass('disabled') ) {
  1186 			return false;
  1231 			return false;
  1187 		}
  1232 		}
  1188 		this.closePopup(t);
  1233 		this.closePopup(t);
  1189 		this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce);
  1234 		this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce);
       
  1235 
       
  1236 		// Clear the selection fields after flipping.
       
  1237 		$( '#imgedit-sel-width-' + postid ).val( '' );
       
  1238 		$( '#imgedit-sel-height-' + postid ).val( '' );
       
  1239 		this.currentCropSelection = null;
  1190 	},
  1240 	},
  1191 
  1241 
  1192 	/**
  1242 	/**
  1193 	 * Crops the image.
  1243 	 * Crops the image.
  1194 	 *
  1244 	 *
  1217 			sel.fh = h;
  1267 			sel.fh = h;
  1218 			this.addStep({ 'c': sel }, postid, nonce);
  1268 			this.addStep({ 'c': sel }, postid, nonce);
  1219 		}
  1269 		}
  1220 
  1270 
  1221 		// Clear the selection fields after cropping.
  1271 		// Clear the selection fields after cropping.
  1222 		$('#imgedit-sel-width-' + postid).val('');
  1272 		$( '#imgedit-sel-width-' + postid ).val( '' );
  1223 		$('#imgedit-sel-height-' + postid).val('');
  1273 		$( '#imgedit-sel-height-' + postid ).val( '' );
  1224 		$('#imgedit-start-x-' + postid).val('0');
  1274 		$( '#imgedit-start-x-' + postid ).val( '0' );
  1225 		$('#imgedit-start-y-' + postid).val('0');
  1275 		$( '#imgedit-start-y-' + postid ).val( '0' );
       
  1276 		this.currentCropSelection = null;
  1226 	},
  1277 	},
  1227 
  1278 
  1228 	/**
  1279 	/**
  1229 	 * Undoes an image edit action.
  1280 	 * Undoes an image edit action.
  1230 	 *
  1281 	 *
  1310 			xS = this.intval( elX1.val() ), yS = this.intval( elY1.val() ),
  1361 			xS = this.intval( elX1.val() ), yS = this.intval( elY1.val() ),
  1311 			x = this.intval( elX.val() ), y = this.intval( elY.val() ),
  1362 			x = this.intval( elX.val() ), y = this.intval( elY.val() ),
  1312 			img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(),
  1363 			img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(),
  1313 			sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi;
  1364 			sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi;
  1314 
  1365 
       
  1366 		this.currentCropSelection = null;
       
  1367 
  1315 		if ( false === this.validateNumeric( el ) ) {
  1368 		if ( false === this.validateNumeric( el ) ) {
  1316 			return;
  1369 			return;
  1317 		}
  1370 		}
  1318 
  1371 
  1319 		if ( x < 1 ) {
  1372 		if ( x < 1 ) {
  1333 			y1 = ( yS === sel.y1 ) ? sel.y1 : Math.round( yS * sizer );
  1386 			y1 = ( yS === sel.y1 ) ? sel.y1 : Math.round( yS * sizer );
  1334 
  1387 
  1335 			if ( x2 > imgw ) {
  1388 			if ( x2 > imgw ) {
  1336 				x1 = 0;
  1389 				x1 = 0;
  1337 				x2 = imgw;
  1390 				x2 = imgw;
  1338 				elX.val( Math.round( x2 / sizer ) );
  1391 				elX.val( Math.min( this.hold.w, Math.round( x2 / sizer ) ) );
  1339 			}
  1392 			}
  1340 
  1393 
  1341 			if ( y2 > imgh ) {
  1394 			if ( y2 > imgh ) {
  1342 				y1 = 0;
  1395 				y1 = 0;
  1343 				y2 = imgh;
  1396 				y2 = imgh;
  1344 				elY.val( Math.round( y2 / sizer ) );
  1397 				elY.val( Math.min( this.hold.h, Math.round( y2 / sizer ) ) );
  1345 			}
  1398 			}
  1346 
  1399 
  1347 			ias.setSelection( x1, y1, x2, y2 );
  1400 			ias.setSelection( x1, y1, x2, y2 );
  1348 			ias.update();
  1401 			ias.update();
  1349 			this.setCropSelection(postid, ias.getSelection());
  1402 			this.setCropSelection(postid, ias.getSelection());
       
  1403 			this.currentCropSelection = ias.getSelection();
  1350 		}
  1404 		}
  1351 	},
  1405 	},
  1352 
  1406 
  1353 	/**
  1407 	/**
  1354 	 * Rounds a number to a whole.
  1408 	 * Rounds a number to a whole.