From: <mol...@us...> - 2011-05-06 15:15:05
|
Revision: 3446 http://openutils.svn.sourceforge.net/openutils/?rev=3446&view=rev Author: molaschi Date: 2011-05-06 15:14:56 +0000 (Fri, 06 May 2011) Log Message: ----------- MEDIA-226 Modified Paths: -------------- trunk/openutils-mgnlmedia/src/main/resources/META-INF/media.tld trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/media.tag Added Paths: ----------- trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/crop.tag trunk/openutils-mgnlmedia/src/main/resources/mgnl-resources/media/js/crop/ trunk/openutils-mgnlmedia/src/main/resources/mgnl-resources/media/js/crop/crop.js Modified: trunk/openutils-mgnlmedia/src/main/resources/META-INF/media.tld =================================================================== --- trunk/openutils-mgnlmedia/src/main/resources/META-INF/media.tld 2011-05-03 12:35:16 UTC (rev 3445) +++ trunk/openutils-mgnlmedia/src/main/resources/META-INF/media.tld 2011-05-06 15:14:56 UTC (rev 3446) @@ -35,6 +35,12 @@ ]]> </example> </tag-file> + <tag-file> + <description>Allow editors to crop (zoom and pan) an image</description> + <display-name>Crop Tag</display-name> + <name>crop</name> + <path>/META-INF/tags/media/crop.tag</path> + </tag-file> <function> <description>Get the media module instance.</description> <display-name>module</display-name> @@ -327,4 +333,11 @@ <function-class>net.sourceforge.openutils.mgnlmedia.media.tags.el.MediaEl</function-class> <function-signature>java.util.Iterator mediaNodesInPlaylist(java.lang.Object)</function-signature> </function> + <function> + <description></description> + <display-name>replaceParam</display-name> + <name>replaceParam</name> + <function-class>net.sourceforge.openutils.mgnlmedia.media.tags.el.MediaEl</function-class> + <function-signature>java.lang.String replaceParam(java.lang.String, java.lang.String)</function-signature> + </function> </taglib> \ No newline at end of file Added: trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/crop.tag =================================================================== --- trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/crop.tag (rev 0) +++ trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/crop.tag 2011-05-06 15:14:56 UTC (rev 3446) @@ -0,0 +1,132 @@ +<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:cms="urn:jsptld:cms-taglib" + xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core" xmlns:media="http://net.sourceforge.openutils/mgnlMedia" + xmlns:cmsfn="http://www.magnolia.info/tlds/cmsfn-taglib.tld" xmlns:fn="http://java.sun.com/jsp/jstl/functions"> + <jsp:directive.attribute name="property" required="true" rtexprvalue="true" type="java.lang.String" /> + <jsp:directive.attribute name="width" required="true" rtexprvalue="true" type="java.lang.Integer" /> + <jsp:directive.attribute name="height" required="true" rtexprvalue="true" type="java.lang.Integer" /> + <jsp:directive.attribute name="item" required="false" rtexprvalue="true" type="java.lang.Object" /> + <jsp:directive.attribute name="node" required="false" rtexprvalue="true" type="java.lang.String" /> + <jsp:directive.attribute name="jqueryui" required="false" rtexprvalue="true" type="java.lang.Boolean" /> + <jsp:directive.attribute name="jquery" required="false" rtexprvalue="true" type="java.lang.Boolean" /> + <jsp:directive.attribute name="loadjs" required="false" rtexprvalue="true" type="java.lang.Boolean" /> + <jsp:directive.attribute name="isEditMode" required="false" rtexprvalue="true" type="java.lang.Boolean" /> + <c:set var="isEditMode" value="${empty isEditMode ? mgnl.editMode and cmsfn:canEdit() : isEditMode}" /> + <c:if test="${isEditMode}"> + <c:set var="uuidBrandLink" value="uuid=${param.uuid}&" /> + </c:if> + <c:if test="${empty node}"> + <c:set var="node" value="${content.handle}" /> + </c:if> + <cms:setNode path="${node}" var="pzcNode" /> + <c:if test="${empty item}"> + <c:set var="item" value="${pzcNode[property]}" /> + </c:if> + <c:set var="loadjs" value="${empty loadjs ? true : loadjs}" /> + <c:set var="itemNode" value="${media:node(item)}" /> + <c:choose> + <c:when test="${(media:width(itemNode) ge width) and (media:height(itemNode) ge height)}"> + <c:set var="property" value="${property}_pzc" /> + <c:set var="pzcId" value="${node}.${property}" /> + <c:set var="pzcProperties" value="${pzcNode[property]}" /> + <c:if test="${isEditMode and (empty pzcJsIncluded or not pzcJsIncluded)}"> + <script type="text/javascript"> var crop_app_ctx = '${pageContext.request.contextPath}';</script> + <c:if test="${loadjs}"> + <c:if test="${empty jquery or jquery}"> + <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"><!-- --> + </script> + </c:if> + <c:if test="${empty jqueryui or jqueryui}"> + <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.12/jquery-ui.min.js"><!-- --> + </script> + </c:if> + <script type="text/javascript" src="${pageContext.request.contextPath}/.resources/media/js/crop/crop.js"><!-- --> + </script> + </c:if> + <c:set var="pzcJsIncluded" value="${true}" scope="request" /> + </c:if> + <c:choose> + <c:when + test="${((mgnl.editMode and cmsfn:canEdit()) or (not empty isEditMode and isEditMode)) and param.pzcId eq pzcId}"> + <c:set var="cropScriptRequired" value="${true}" scope="request" /> + <c:set var="size" value="${media:size(media:node(item), 'original')}" /> + <c:if test="${empty pzcProperties}"> + <c:set var="pzcProperties" value="100|0|0" /> + </c:if> + <c:set var="pzcParams" value="${fn:split(pzcProperties, '|')}" /> + <c:set var="zoom" value="${(0 + pzcParams[0]) / 100}" /> + <c:set var="zoomW" value="${zoom * size[0]}" /> + <c:set var="zoomH" value="${zoom * size[1]}" /> + <c:set var="marginX" value="${size[0] - zoomW}" /> + <c:set var="marginY" value="${size[1] - zoomH}" /> + <c:set var="panX" value="${size[0] - width - pzcParams[1] - marginX}" /><!-- zoomW - width}" /> --> + <c:set var="panY" value="${size[1] - height - pzcParams[2] - marginY}" /> + <div id="${pzcId}" class="pzc" + style="width:${width}px;height:${height}px;padding:0;margin:0;border:0;position:relative" data-width="${size[0]}" + data-height="${size[1]}" data-property="${property}" data-node="${node}"> + <div class="pzcMask" style="overflow:hidden;width:100%;height:100%;padding:0;margin:0;border:0;position:relative"> + <div class="pzcContainment" + style="width:${2 * size[0] - width}px;height:${2 * size[1] - height}px;left:${width - size[0]}px;top:${height - size[1]}px;padding:0;margin:0;border:0;position:relative"> + <div class="pzcMedia" + style="left:${panX}px;top:${panY}px;width:${zoomW}px;height:${zoomH}px;padding: ${marginY}px ${marginX}px;margin:0;border:0;position:absolute"> + <img src="${appCtx}${media:url(media:node(item))}" style="width:100%;height:100%" /> + </div> + </div> + </div> + <a class="pzcEdit pzcExit" href="${media:replaceParam('pzcId', '')}" title="exit" + style="position:absolute;right:5px;top:5px;background:#000 url(${appCtx}/.resources/media/icons/crop/exit.png) center center no-repeat;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;width:24px;height:24px;"> + <!-- --> + </a> + <a class="pzcEdit pzcSave" href="${media:replaceParam('pzcId', '')}" title="save" + style="position:absolute;right:5px;top:34px;background:#000 url(${appCtx}/.resources/media/icons/crop/save.png) center center no-repeat;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;width:24px;height:24px;"> + <!-- --> + </a> + <div class="pzcZoomPanel" + style="display:none;position:absolute;border:none;padding:10px;bottom:20px;left:50%;margin-left:-20px;width:40px;text-align:center;background:#000;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;color:#fff;font-size:16px;font-family:Verdana;line-height:20px;height:20px;"><!-- --> + </div> + <div class="pzcSlider" + style="position:absolute;padding:0;margin:5px;width:100px;height:7px;bottom:0px;left:50%;margin-left:-50px;border:solid 1px #999"><!-- --> + </div> + </div> + </c:when> + <c:otherwise> + <c:set var="res" value="p${width}x${height}" /> + <c:if test="${not empty pzcProperties}"> + <c:set var="res" value="${res};pzc=${pzcProperties},quality=1" /> + </c:if> + <c:choose> + <c:when test="${((mgnl.editMode and cmsfn:canEdit()) or (not empty isEditMode and isEditMode))}"> + <div id="${pzcId}" + style="overflow:hidden;width:${width}px;height:${height}px;border:0;margin:0;padding:0;position:relative"> + <img src="${appCtx}${media:urlres(media:node(item), res)}" /> + <!-- <media:media item="${item}" width="${width}" height="${height}" resize="crop" />--> + <a class="pzcEdit" href="${media:replaceParam('pzcId', pzcId)}" title="edit" + style="position:absolute;right:5px;top:5px;background:#000 url(${appCtx}/.resources/media/icons/crop/edit.png) center center no-repeat;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;width:24px;height:24px;"> + <!-- --> + </a> + <c:if test="${not empty pzcProperties}"> + <a class="pzcEdit pzcDelete" href="${media:replaceParam('pzcId', '')}" title="reset" id="${node}.${property}" + style="position:absolute;right:5px;top:34px;background:#000 url(${appCtx}/.resources/media/icons/crop/delete.png) center center no-repeat;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;width:24px;height:24px;"> + <!-- --> + </a> + </c:if> + </div> + </c:when> + <c:otherwise> + <c:set var="res" value="${res}" /> + <img src="${appCtx}${media:urlres(media:node(item), res)}" /> + </c:otherwise> + </c:choose> + </c:otherwise> + </c:choose> + </c:when> + <c:otherwise> + <span + style="width:${width - 30}px;height:${height - 30}px;position:relative;border:none;display:block;padding:15px;margin:0;font-size:12px;color:#fff;font-family:Arial;background-color:#C0C0C0;"> + Selected media is too small. + <br /> + Choose media with minimum size of + <b>${width}x${height}</b> + </span> + </c:otherwise> + </c:choose> +</jsp:root> \ No newline at end of file Modified: trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/media.tag =================================================================== --- trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/media.tag 2011-05-03 12:35:16 UTC (rev 3445) +++ trunk/openutils-mgnlmedia/src/main/resources/META-INF/tags/media/media.tag 2011-05-06 15:14:56 UTC (rev 3446) @@ -19,7 +19,9 @@ fit: makes the new image to fit into required resolution. nocrop: makes the new image to contain the required resolution. crop: makes the new image to contain the required res and the crop the simmetric bands that outfit resolution. -fitbands: makes the new image to fit into required res and fills empty areas with background color you pass to in 'parameter' attribute as hex value of 'background' parameter"/> +fitbands: makes the new image to fit into required res and fills empty areas with background color you pass to in 'parameter' attribute as hex value of 'background' parameter. +pzc: apply zoom and crop to image as specified by the pzc parameter (value must be built with the pattern zoom|pan x|pan y, i.e pzc:80|220|125). If no pzc parameter is found the crop mode is applied to image."/> + <jsp:directive.attribute name="parameters" required="false" rtexprvalue="true" description="parameters to pass to image processor as couples key=value joined by commas "/> <jsp:directive.attribute name="ignoreDim" required="false" rtexprvalue="true" type="java.lang.Boolean" description="if true the img element will be rendered without width and height attributes "/> <jsp:directive.attribute name="autoPlay" required="false" rtexprvalue="true" type="java.lang.Boolean" description="auto starts the player without waiting for user play command"/> @@ -30,6 +32,11 @@ <jsp:directive.attribute name="videoImagePreview" required="false" rtexprvalue="true" type="java.lang.Boolean" description="if set to true, the tag will not insert the player for videos but only a preview image. For videos or mp3s it needs the following scripts loaded in page: <ul><li>.resources/media/js/mootools-1.2-core.js</li><li>.resources/media/js/mootools-1.2-more.js</li><li>.resources/media/js/mootools-1.2-swfobject.js</li></ul>"/> <jsp:directive.attribute name="controlbar" required="false" rtexprvalue="true" type="java.lang.String" description="defines controlbar position. Possible values are: 'none' (for hiding), 'over', 'bottom', 'top'. If not set, this value will be 'bottom' by default." /> <jsp:directive.attribute name="share" required="false" rtexprvalue="true" type="java.lang.Boolean" description="if set to true the pluging share-1 is show"/> + <jsp:directive.attribute name="crop" required="false" rtexprvalue="true" type="java.lang.Boolean" description="if true, the zoom and crop mode is enabled on the media. The cropProperty attribute is mandatory"/> + <jsp:directive.attribute name="cropProperty" required="false" rtexprvalue="true" type="java.lang.String" description="the name of the property where (with '_pzc' suffix) zoom and crop informations are saved "/> + <jsp:directive.attribute name="cropJs" required="false" rtexprvalue="true" type="java.lang.Boolean" description="whether to load crop js files. Defaults to true. If false you have to manually include jquery, jquery ui and (before closing body tag) /.resources/media/js/crop/crop.js" /> + <jsp:directive.attribute name="cropJquery" required="false" rtexprvalue="true" type="java.lang.Boolean" description="whether to load jquery library or not. Defaults to true; if cropJs is false jquery is not loaded" /> + <jsp:directive.attribute name="cropJqueryUI" required="false" rtexprvalue="true" type="java.lang.Boolean" description="whether to load jquery UI library or not. Defaults to true; if cropJs is false jquery ui is not loaded" /> <c:if test="${empty item}"> <c:if test="${empty node}"> @@ -60,11 +67,15 @@ <c:set var="mediamodule" value="${media:module()}"/> <c:set var="player" value="${mediamodule.player}" /> </c:if> + <c:set var="crop" value="${empty crop ? false : crop}" /> <c:set value="${media:node(item)}" var="mediaNode" /> <c:choose> <c:when test="${!empty mediaNode}"> <cms:setNode var="media" content="${mediaNode}" /> <c:choose> + <c:when test="${crop and (media.type eq 'image' or media.type eq 'wallpaper' or videoImagePreview)}"> + <media:crop item="${media}" width="${width}" height="${height}" property="${cropProperty}" jquery="${cropJquery}" jqueryui="${cropJqueryUI}" loadjs="${cropJs}" /> + </c:when> <c:when test="${media.type eq 'image' or media.type eq 'wallpaper' or videoImagePreview}"> <c:choose> <c:when test="${width eq 0 and height eq 0}"> @@ -83,6 +94,9 @@ <c:when test="${resize eq 'fit'}"> <c:set var="controlChar" value="l" /> </c:when> + <c:when test="${resize eq 'pzc'}"> + <c:set var="controlChar" value="p" /> + </c:when> </c:choose> <c:if test="${width eq 0}"> <c:set var="controlChar" value="l" /> Added: trunk/openutils-mgnlmedia/src/main/resources/mgnl-resources/media/js/crop/crop.js =================================================================== --- trunk/openutils-mgnlmedia/src/main/resources/mgnl-resources/media/js/crop/crop.js (rev 0) +++ trunk/openutils-mgnlmedia/src/main/resources/mgnl-resources/media/js/crop/crop.js 2011-05-06 15:14:56 UTC (rev 3446) @@ -0,0 +1,173 @@ +(function($) { + function init(container, params) { + var media = container.find(".pzcMedia"); + var mediaImg = container.find(".pzcMedia img"); + var pczZoomPanel = container.find(".pzcZoomPanel"); + var pzcSlider = container.find(".pzcSlider"); + + var modified = false; + + $(media).draggable( { + containment : 'parent', + cursor : 'move', + refreshPositions : true, + start : function() { + modified = true; + } + }); + + var width = container.width(); + var height = container.height(); + + var imgW = parseInt(container.attr('data-width')); + var imgH = parseInt(container.attr('data-height')); + var property = container.attr('data-property'); + var node = container.attr('data-node'); + + var actZoom = Math.min( + parseInt(100 * $(".pzcMedia img").width() / imgW), 100); + var minZoom = Math.max(parseInt(100 * width / imgW), parseInt(100 + * height / imgH)); + + if (width < 100) { + pzcSlider.css( { + width : '' + (width - 10) + 'px', + 'margin-left' : '-' + ((width - 10) / 2) + 'px' + }); + } + + pczZoomPanel.html('' + actZoom + '%'); + + container.find(".pzcExit").click( + function() { + return !modified + || confirm("Are you sure to exit without saving?"); + }); + + container.find(".pzcSave").click( + function() { + var href = $(this).attr('href'); + $.ajax( { + url : crop_app_ctx + '/media/pzc', + data : { + zoom : actZoom, + x : Math.floor(container.offset().left + - mediaImg.offset().left), + y : Math.floor(container.offset().top + - mediaImg.offset().top), + id : property, + handle : node + }, + // type : 'HEAD', + error : function(err) { + alert(err); + }, + success : function(msg) { + location.href = href; + } + }); + return false; + }); + + var zoomFn = function(zoom) { + actZoom = zoom; + pczZoomPanel.html('' + actZoom + '%'); + var w = parseInt(actZoom * imgW / 100); + var h = parseInt(w * imgH / imgW); + if (w >= width && h >= height) { + var newLeft = width - w; + var newTop = height - h; + var left = parseInt(media.css('left')); + var top = parseInt(media.css('top')); + left = (left > w - width) ? w - width : left; + top = (top > h - height) ? h - height : top; + $(".pzcMedia").css( { + width : '' + w + 'px', + height : '' + h + 'px', + left : '' + left + 'px', + top : '' + top + 'px', + padding : '' + (imgH - h) + 'px ' + (imgW - w) + 'px' + }); + } + } + + pzcSlider.slider( { + min : minZoom, + max : 100, + value : actZoom, + slide : function(event, ui) { + modified = true; + zoomFn(ui.value); + } + }); + pzcSlider.fadeTo('slow', 0.4); + pzcSlider.mouseenter(function() { + pzcSlider.fadeTo('slow', 1.0); + pczZoomPanel.fadeTo('slow', 0.7); + }); + pzcSlider.mouseleave(function() { + pzcSlider.fadeTo('slow', 0.4); + pczZoomPanel.fadeTo('slow', 0); + }); + + // zoomFn(actZoom); + } + ; + + $.fn.mgnlMediaPZC = function(params) { + var params = $.extend( { + /* + * defaultOpened : 1, tabLinks : '.tablinks a[href^=#]', tabContents : + * '.tab section' + */ + }, params); + this.each(function(i, el) { + init($(el), params); + }); + return this; + }; + +})($); + +$('head') + .append( + '<link type="text/css" rel="stylesheet" href="'+ crop_app_ctx +'/.resources/media/css/crop/pzc.css" />'); +$('head') + .append( + '<link type="text/css" rel="stylesheet" href="'+ crop_app_ctx +'/.resources/media/css/crop/jquery-ui-1.8.12.custom.css" />'); + +var refreshMediaPZC = function() { + $(".pzc").mgnlMediaPZC(); + $(".pzcEdit").fadeTo('slow', 0.4); + $(".pzcEdit").mouseenter(function() { + $(this).fadeTo('slow', 1.0); + }); + $(".pzcEdit").mouseleave(function() { + $(this).fadeTo('slow', 0.4); + }); + $(".pzcDelete").click(function() { + var href = $(this).attr('href'); + var aId = $(this).attr('id'); + var node = aId.split('.')[0]; + var property = aId.split('.')[1]; + $.ajax( { + url : crop_app_ctx +'/media/pzc', + data : { + command : 'delete', + id : property, + handle : node + }, + // type : 'HEAD', + error : function(err) { + alert(err); + }, + success : function(msg) { + location.href = href; + } + }); + return false; + }); +} + +$(document).ready(refreshMediaPZC); +$(document).ajaxSuccess(refreshMediaPZC); \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |