I am using unitegallery within an xpage. here is the code:
<div id="gallery" style="display:none;">
<xp:repeat rows="100" value="#{javascript:Album.getPictures();}" var="obj" indexVar="idx" disableOutputTag="true" removeRepeat="true">
<xp:text escape="true">
<xp:this.value>
<![CDATA[#{javascript:var db = datasource.getString('DB_FILEPATH');
var id = obj;
var Picture = new org.openntf.bildr.Picture();
Picture.loadByUnid(obj);
var original = Picture.getOriginal();
var pic = "../" + db + "/0/" + id + "/$FILE/" + original;
return '<img src="' + pic + '" data-image="' + pic + '"></img>'}]]></xp:this.value>
</xp:text>
<xp:image rendered="false">
<xp:this.attrs>
<xp:attr name="data-image">
<xp:this.value>
<![CDATA[#{javascript:var db = datasource.getString('DB_FILEPATH');
var id = obj;
var Picture = new org.openntf.bildr.Picture();
Picture.loadByUnid(obj);
var original = Picture.getOriginal();
return "../" + db + "/0/" + id + "/$FILE/" + original;}]]>
</xp:this.value>
</xp:attr>
</xp:this.attrs>
<xp:this.url>
<![CDATA[#{javascript:var db = datasource.getString('DB_FILEPATH');
var id = obj;
var Picture = new org.openntf.bildr.Picture();
Picture.loadByUnid(obj);
var thumb = Picture.getThumb();
return "../" + db + "/0/" + id + "/$FILE/" + thumb;}]]>
</xp:this.url>
</xp:image>
</xp:repeat>
</div>
<!--/#gallery -->
(the sample contains an attempt with an xp:image and xp:text control)
This delivers me the images in the gallery, however the rest of the function in my xpages freezes e.g. buttons.
Anyone know a solution for this?
The problem is related to AMD loading complications in Notes 9. After using the xsnippet from Ferry Kranenburg for AMD loading the problem is gone.
Related
Hi the only thing I would like to have in JSSOR is to toggle fullscreen gallery. I am using Image gallery version of JSSOR. I would like to have fullscreen button on the right upper corner which toggles fullscreen (not full but maximized) view and I can move with images there.
I did not see any tutorial on official jssor page or any other thread.
I would like to have something like this in the upper right corner. Any help with this ?
<script src="jssor.slider.min.js"></script>
<div id="jssor_1" style="position:relative;top:0px;left:0px;width:980px;height:380px;overflow:hidden;">
<div data-u="slides" style="position:absolute;top:0px;left:0px;width:980px;height:380px;overflow:hidden;">
<div><img data-u="image" src="image1.jpg" /></div>
<div><img data-u="image" src="image2.jpg" /></div>
</div>
<!-- https://www.jssor.com/development/slider-with-fixed-static-element.html -->
<img id="fullscreen_toggle_button" src="toggle-fullscreen.png" style="position:absolute;top:5px;right:5px;" />
</div>
<script>
var options = { $AutoPlay: 1 };
var jssor_1_slider_element = document.getElementById("jssor_1");
var jssor_1_slider_parent_element = jssor_1_slider_element.parentNode;
var jssor_1_slider = new $JssorSlider$(jssor_1_slider_element, options);
var isFullscreenMode = false;
var fullscreenElement;
var fullscreen_toggle_button_element = document.getElementById("fullscreen_toggle_button");
function ToggleFullscreen() {
isFullscreenMode = !isFullscreenMode;
if(isFullscreenMode) {
//create fullscreen div, move jssor slider into the div
fullscreenElement = document.createElement("div");
fullscreenElement.style.position = "fixed";
fullscreenElement.style.top = 0;
fullscreenElement.style.left = 0;
fullscreenElement.style.width = "100%";
fullscreenElement.style.height = "100%";
fullscreenElement.style.zIndex = 1000000;
document.body.appendChild(fullscreenElement);
var fullscreenRect = fullscreenElement.getBoundingClientRect();
var width = fullscreenRect.right - fullscreenRect.left;
var height = fullscreenRect.bottom - fullscreenRect.top;
fullscreenElement.appendChild(jssor_1_slider_element);
jssor_slider.$ScaleSize(width, height);
}
else if(fullscreenElement) {
//move jssor slider into its original container, remove the fullscreen div
jssor_1_slider_parent_element.appendChild(jssor_1_slider_element);
var width = jssor_1_slider_parent_element.clientWidth;
jssor_slider.$ScaleWidth(width);
document.body.removeChild(fullscreenElement);
fullscreenElement = null;
}
}
fullscreen_toggle_button_element.addEventListener("click", ToggleFullscreen);
</script>
I am having troubles setting viewScope from jsonRPC via button (onClick).
See code below.
I am using a browser (FF/Chrome Mac & PC) to access the XPage.
After clicking the button i get message "RPC done" as expected,
but the viewScope is not set.
<xe:jsonRpcService id="myRpc" serviceName="myRpcService">
<xe:this.methods>
<xe:remoteMethod name="setDialogValues">
<xe:this.script><![CDATA[var success = false;
try {
viewScope.put("dojoDialog_title", "Window title");
success = true;
} catch (e) {
success = false;
}
return success;]]></xe:this.script>
</xe:remoteMethod>
</xe:this.methods>
</xe:jsonRpcService>
<xp:button value="Set viewScope via RPC" id="setVSButton">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[var remoteMethod = myRpcService.setDialogValues();
remoteMethod.addCallback(function(response){
if(response===true){
alert("RPC done");
}else{
alert("ERROR");
}
});]]></xp:this.script>
</xp:eventHandler>
</xp:button>
EDIT:
What I ultimately want to achieve is setting ViewScope parameters for a dojo dialog. The dialog is opened via CSJS, reads the ViewScope variables and displays the correct page, size and title.
What I have tried successfully is using a label to set ViewScope before opening the dialog. My experience tells me this is a quick and dirty solution that might crash and burn at any time. Surely there must be a better / correct way to set ViewScope or run SSJS before running CSJS?
See code excerpt below.
Label - Execute SSJS (Set ViewScope for dialog)
<xp:label id="labelSetParamsBeforeOpeningDialog">
<xp:this.value><![CDATA[#{javascript:
var result = '';
try{
if(param.containsKey('runCode')){
if(param.runCode){
var title = param.title;
var width = param.width;
var height = param.height;
var dialogType = param.dialogType;
var parentUnid = viewScope.get("currentDocUnid");
var pageToOpen = "";
switch(dialogType){
case "one":
//Dialog type specific code goes here
pageToOpen = "dojoDialog_one.xsp?open&parent="+ parentUnid +"&dialog=true";
break;
case "two":
viewScope.put("checkForConflicts", true);
pageToOpen = 'dojoDialog_two.xsp?open&parent='+ parentUnid;
break;
case "three":
pageToOpen = "dojoDialog_three.xsp?open&parent="+ parentUnid;
break;
default:
pageToOpen = "error-page.xsp?open";
break;
}
viewScope.put('dojoDialog_parentunid', parentUnid);
viewScope.put('dojoDialog_pageToOpen', pageToOpen);
viewScope.put('dojoDialog_title', title);
viewScope.put('dojoDialog_width', width);
viewScope.put('dojoDialog_height', height);
}
}
}catch (e){
result = "ERROR:"+ e.message;
}
return result;
}]]></xp:this.value>
</xp:label>
Button - Run SSJS (label) then open dialog (CSJS)
<xp:button value="Show dialog three" id="myButton">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[
var title = 'THREE';
var width = 1200;
var height = 440;
var dialogType = 'three';
XSP.partialRefreshGet("#{id:labelSetParamsBeforeOpeningDialog}",
{
params: {"runCode":true, "title":title, "width":width, "height":height,"dialogType":dialogType},
onStart: function(){
//nothing
},
onError: function(){
alert("ERROR")
},
onComplete: function(){
XSP.openDialog('#{id:inPlaceDialog}');
}
});]]></xp:this.script>
</xp:eventHandler>
</xp:button>
Dojo dialog - Reads ViewScope
<xe:dialog id="inPlaceDialog" style="height:auto;width:auto"
dojoType="com.ZetaOne.widget.Dialog">
<xe:this.title>
<![CDATA[#{javascript:var title =
viewScope.get("dojoDialog_title");return title;}]]>
</xe:this.title>
<xe:this.dojoAttributes>
<xp:dojoAttribute name="autofocus" value="false"></xp:dojoAttribute>
</xe:this.dojoAttributes>
<xc:global_dojoDialog_iframe
elementSRC="#{javascript:applicationScope.dbPath}/#
{javascript:viewScope.dojoDialog_page}"
elementUnid="#{javascript:viewScope.dojoDialog_unid;}"
elementParentUnid="#{javascript:viewScope.dojoDialog_parentunid;}"
elementDialogWidth="#{javascript:viewScope.dojoDialog_width;}"
elementDialogHeight="#{javascript:viewScope.dojoDialog_height;}">
</xc:global_dojoDialog_iframe>
<xp:eventHandler event="onShow" submit="false">
<xe:this.script><![CDATA[dojo.query("img[aria-label='close
button']").forEach(function(el){
el.src = "blank_x.gif";
});]]></xe:this.script>
</xp:eventHandler>
</xe:dialog>
From what I've seen JSON RPC is doesn't update the component tree at all. So viewScope can't be updated from a JSON RPC call. See http://www.intec.co.uk/json-rpc-service-component-tree-manipulation-openlog/
If you want to update viewScope, I'm not sure why you would use a JSON RPC call over a partial refresh (GET or POST).
I would like to make a confirmation before continue. I mean rest of codes should not run a until a user make a decision (Yes/No). If a user push the button "YES" It should create a new document. If the user chose "NO" nothing should happen.
in this code a confirmation dialog appears that asks "Are you sure to create new Document" My problem is
a new document is already created If the user chose "Yes or no". this codes below does not care answer in the Dialog? Whole code runs then that dialog appears. I think i miss something :(
var dateOther = docOther.getFirstItem("TarihBitis").getDateTimeValue();
if (dateOther==null)
{
var dlgA = getComponent("dialogTarifeConfirm");
dlgA.show();
//Creating New Doc...
var docNew = database.createDocument();
docNew.appendItemValue("Subject", requestScope.subject);
docNew.appendItemValue("fieldName1", viewScope.fieldName1);
docNew.appendItemValue("fieldName2", viewScope.fieldName2);
docNew.save();
}
Any suggestion is appreciated.
Regards
Cumhur Ata
UPDATE 1 : Please find Where i am mixed after the dialog codes does not care the answer both document are created then the dialog will appear on the screen. I think I miss something that I don't know.
try
{
//Sync backend document with changes made in the frontend document
var doc:NotesDocument = document1.getDocument(true);
var today:NotesDateTime = session.createDateTime(#Now());
var bugun:java.util.Date = new java.util.Date();
var dateFormat = new java.text.SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
cn = sessionScope.commonUserName;
//getCurrnetUserName as String
var user:String=session.getEffectiveUserName();
var tKey = doc.getItemValueString("ParentUNID");
var ParaBirimi = document1.getItemValueString("ParaBirimi");
var tarifeView:NotesView = database.getView("(viewStandartTarifelerKontrol)");
var vec:NotesViewEntryCollection = tarifeView.getAllEntriesByKey(ParaBirimi);
var docBuUNID = document1.getDocument().getUniversalID();
if(document1.isNewNote())
{
if (vec.getCount() > 0)
{
var entry1:NotesViewEntry = vec.getFirstEntry();
while (entry1!= null)
{
var tarifeDoc:NotesDocument = entry1.getDocument();
var tarifeUNID = tarifeDoc.getUniversalID();
var ParentUNID = tarifeDoc.getItemValueString("ParentUNID");
if (docBuUNID!=tarifeUNID)
{
var tarifeDocBasDate:NotesDateTime = tarifeDoc.getItemValueDateTimeArray("startDate").elementAt(0);
var docBuBasDate:NotesDateTime = doc.getItemValueDateTimeArray("startDate").elementAt(0);
var days:int = tarifeDocBasDate.timeDifferenceDouble(docBuBasDate) / 86400;
diff = docBuBasDate.timeDifference(tarifeDocBasDate)/86400;
var a = tarifeDoc.getFirstItem("endDate").getDateTimeValue();
if (a==null)
{
if(diff>0)
{
var a = getComponent("dialogConfirm1");
a.show();
//If the user say YES FORMA document will be created.
var docNew = database.createDocument();
docNew.appendItemValue("Subject", viewScope.subject);
docNew.appendItemValue("Form","FormA");
//If the user say NO FORMB document will be created.
var docNew = database.createDocument();
docNew.appendItemValue("Subject", viewScope.subject);
docNew.appendItemValue("Form","FormB");
docNew.save();
}
}
}
var tmpentry = vec.getNextEntry();
entry1.recycle();
entry1 = tmpentry;
}
}
}
}
catch(e)
{
print(e);
}
1. Create a button for opening your dialog:
<xp:button id="btnDialogTarifeConfirm" value="Create New Document">
<xp:eventHandler event="onclick" submit="true" execMode="partial" execId="btnDialogTarifeConfirm">
<xp:this.action><![CDATA[#{javascript:var dialogTarifeConfirm:com.ibm.xsp.extlib.component.dialog.UIDialog = getComponent("dialogTarifeConfirm");
dialogTarifeConfirm.show();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
2. Behind your dialogs button btnCreateNewDocument your code should be placed:
<xe:dialog id="dialogTarifeConfirm" title="Create New Document">
...
<xp:div styleClass="lotusDialogFooter">
<xp:button id="btnCreateNewDocument" value="YES (Create New Document)">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="lotusForm"
execMode="partial" execId="btnCreateNewDocument">
<xp:this.action><![CDATA[#{javascript://Creating New Doc...
var docNew = database.createDocument();
docNew.appendItemValue("Subject", requestScope.subject);
docNew.appendItemValue("fieldName1", viewScope.fieldName1);
docNew.appendItemValue("fieldName2", viewScope.fieldName2);
docNew.save();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:link escape="true" text="No" themeId="Link.Action"
onclick="XSP.closeDialog('#{id:dialogTarifeConfirm}')">
</xp:link>
</xp:div>
</xe:dialog>
I hope this helps
Can you not use "this.message"?
A simple example of using it to delete documents could be:
<xp:button value="Delete" id="button3"
styleClass="btn btn-danger btn-block btn-xs">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:confirm>
<xp:this.message><![CDATA[#{javascript:"Are you sure you want to delete this document?"}]]></xp:this.message>
</xp:confirm>
<xp:actionGroup>
<xp:this.condition><![CDATA[#{javascript:var id = rowData.getUniversalID();
var doc:NotesDocument = database.getDocumentByUNID(id);
doc.remove(true);}]]></xp:this.condition>
</xp:actionGroup>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
I have a nice DataView, with only one thing wrong. The width of the extra columns keeps changing depending on the width of the data in the field. I think it looks much better if these values do not jump around.
How can I set the width of these columns? I tried using a width with !important in the style of the extra columns, but that didn't work. I tried adding &NBSP to the values, but that didn't work perfectly, and is really really kludgy.
<xe:dataView id="dataView1" var="dvEntry"
collapsibleDetail="false" columnTitles="true"
detailsOnClient="true" openDocAsReadonly="true" rows="25"
disableTheme="false" pageName="/xpFormEmployee.xsp"
styleClass="lotusTable" rowStyleClass="EVEN,ODD"
rowStyle="width:1000px">
<xe:this.data>
<xp:dominoView var="view1"
viewName="(xpEmployeeByNameActiveOnly)"
databaseName="TheTruth.nsf" dataCache="id"
searchExactMatch="false">
<xp:this.search><![CDATA[#{javascript:var query:String = '';
var search:String = viewScope.get("searchString")
if (search === null || search == "")
{query = ""}
else
{query = 'FIELD HR_FullName CONTAINS ' + search + '*'}
return query
}]]></xp:this.search>
</xp:dominoView>
</xe:this.data>
<xe:this.extraColumns>
<xe:viewExtraColumn
style="width:400px !important;vertical-align:middle;font-weight:bold"
headerStyle="font-weight:bold;font-size:12pt" contentType="html"
columnTitle="Location">
<xe:this.href><![CDATA[#{javascript:var geoView:NotesView = database.getView("(DbLookupLocationsByName)");
var geoDoc:NotesDocument;
var UNID:String;
geoDoc = geoView.getDocumentByKey(dvEntry.getColumnValue("HR_GeoLocation"));
if (geoDoc != null)
{
UNID = geoDoc.getUniversalID();
"notes://XX/__86257D58005E456E.nsf/0/" + UNID + "?OpenDocument"}
else
{""}}]]></xe:this.href>
<xe:this.value><![CDATA[#{javascript:var tmpLoc:String = dvEntry.getColumnValue("HR_geoLocation");
var lenTmpLoc = 30 - tmpLoc.length;
var tmpPad:String = "";
for (i = 0; i < (lenTmpLoc); i++)
{tmpPad += " ";}
return tmpLoc + tmpPad
}]]></xe:this.value>
</xe:viewExtraColumn>
<xe:viewExtraColumn columnTitle="Office Phone"
columnName="HR_OfficePhone"
style="width:400px !important;vertical-align:middle"
headerStyle="font-weight:bold;font-size:12pt"
contentType="html">
<xe:this.value><![CDATA[#{javascript:var tmpLoc:String = dvEntry.getColumnValue("HR_officePhone");
var lenTmpLoc = 50 - tmpLoc.length;
var tmpPad:String = "";
for (i = 0; i < (lenTmpLoc); i++)
{tmpPad += " ";}
return tmpLoc + tmpPad
}]]></xe:this.value>
</xe:viewExtraColumn>
<xe:viewExtraColumn></xe:viewExtraColumn>
</xe:this.extraColumns>
<xe:this.iconColumn>
<xe:viewIconColumn>
<xe:this.icons>
<xe:iconEntry
style="height:35px;width:35px;padding-right:5.0px">
<xe:this.url><![CDATA[#{javascript:var phtStr:String;
var imgNme:String;
phtStr = dvEntry.getColumnValue("photo");
var docUNID:String = dvEntry.getColumnValue("docUNID");
if (phtStr != "")
{imgNme = "XXXXXX/xsp/.ibmmodres/domino/OpenAttachment/XXXX" + docUNID + "/$File/" + phtStr + "?Open"}
else
{imgNme = "xpPhotoPlaceholder.gif"}
imgNme
}]]></xe:this.url>
</xe:iconEntry>
</xe:this.icons>
</xe:viewIconColumn>
</xe:this.iconColumn>
<xe:this.summaryColumn>
<xe:viewSummaryColumn columnTitle="Name"
headerStyle="font-weight:bold;font-size:12pt;padding-left:8.0px">
</xe:viewSummaryColumn>
</xe:this.summaryColumn>
<xp:this.facets>
<xp:panel xp:key="summary">
<xp:table>
<xp:tr>
<xp:td>
<xp:text escape="false"
id="computedField2">
<xp:this.value><![CDATA[#{javascript:return "<h4><a href='xpFormEmployee.xsp?openDocument&documentId=" + dvEntry.getUniversalID() + "'>" + dvEntry.getDocument().getItemValueString('HR_FullName') + "</a></h4>";
}]]></xp:this.value>
</xp:text>
</xp:td>
</xp:tr>
</xp:table>
</xp:panel>
<xe:pagerSizes id="pagerSizes1"
sizes="5|10|25|50|100" xp:key="pagerTopLeft">
</xe:pagerSizes>
<xp:panel xp:key="pagerBottomLeft"
id="panel3">
<xe:pagerSizes id="pagerSizes2"></xe:pagerSizes>
</xp:panel>
<xp:panel xp:key="pagerTopRight"
styleClass="panelPagerTopRight">
<xp:pager layout="Previous Group Next"
for="dataView1" id="pager3" partialRefresh="true"
styleClass="pager">
</xp:pager>
</xp:panel>
<xp:panel xp:key="pagerBottomRight">
<xp:pager layout="Previous Group Next"
for="dataView1" id="pager1" partialRefresh="true"
styleClass="pager">
</xp:pager>
</xp:panel>
<xp:panel xp:key="noRows">
<xp:br />
<xp:div styleClass="xlEmptyFacet">
<xp:label>
<xp:this.value><![CDATA[#{javascript:"No Documents Found"}]]></xp:this.value>
</xp:label>
</xp:div>
</xp:panel>
</xp:this.facets>
</xe:dataView>
Change style of class lotusTable to
.lotusTable {
table-layout: fixed;
}
Then style width= in column's headerStyle or style won't be ignored anymore.
Example:
Assuming css code from above is in Style Sheets Resource "fixedTable.css" then you can set columns' widths this way
<xp:this.resources>
<xp:styleSheet
href="/fixedTable.css"></xp:styleSheet>
</xp:this.resources>
<xe:dataView ...>
...
<xe:this.extraColumns>
<xe:viewExtraColumn
headerStyle="width:10%;" ...>
...
</xe:viewExtraColumn>
<xe:this.extraColumns>
<xe:viewExtraColumn
headerStyle="width:20%;" ...>
...
</xe:viewExtraColumn>
<xe:this.summaryColumn>
<xe:viewSummaryColumn
headerStyle="width:70%;" ...>
</xe:viewSummaryColumn>
</xe:this.summaryColumn>
...
</xe:dataView>
All,
I have a SVG rectangle in my application which can be stretched horizontally by dragging the end bar (left & right) on either side of the rectangle. The rectangle can be
(1) resized (by stretching as per above),
(2)dragged,
(3)& rotated.
Everything works fine, however, one strange experience is that when I rotate the rectangle to a degree close to 90, & then try to resize the rectangle, it starts stretching from the opposite border of the rectangle instead of the original borders. (here is the image):
It appears to be getting confused between left and right when I use the rotate function.
Here is the revised HTML, JS & SVG:
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
<!-- <script type="text/javascript" src="CPolyline.js">
</script>-->
</head>
<body>
<object id="oo" data="rect2.svg" style="position:fixed;width: 800px;height:800px;bottom:-100px;right: 375px;">
</object>
path: <input type="button" id="path" onclick="X()">
path2: <input type="button" id="path2" onclick="Y()">
<input type="button" value="Rotate" onclick="Rotate1()">
<script type="text/javascript">
var ob=document.getElementById("oo")
var svgDoc=null;
var svgRoot=null;
var MyGroupObjectsObj = null;
var svgNS = "http://www.w3.org/2000/svg";
var dragTarget = null;
var rectTemplate = null;
var grabPoint = null;
var clientPoint = null;
var rectX = null;
var rectY = null;
var rectWidth = null;
var rectHeight = null;
var arr=new Array();
var resizingLeft = false;
var resizingRight = false;
var rectrot=null
ob.addEventListener("load", function(){
svgDoc=ob.contentDocument;
svgRoot=svgDoc.documentElement;
grabPoint = svgRoot.createSVGPoint();
clientPoint = svgRoot.createSVGPoint();
rectTemplate = svgDoc.getElementById('rectTemplate')
rectrot=svgDoc.getElementById("rect1")
}, false)
var angel=0
function Rotate1()
{
angel=angel+10
//alert(rectrot)
var c=rectTemplate.getAttribute("transform");
var widt=Number(rectTemplate.getAttribute("width"))/2;
var hie=Number(rectTemplate.getAttribute("height"))/2
var tran=c.match(/[\d\.]+/g);
var newxpo=Number(tran[0])+widt;
var newypo=Number(tran[1])+hie;
var r=Math.tan((newxpo)/(newypo))
rectTemplate.parentNode.setAttribute("transform","translate("+newxpo+" "+newypo+")"+"rotate("+angel+") translate("+(newxpo*-1)+" "+(newypo*-1)+")");
}
function MouseDown(evt)
{
var targetElement = evt.target;
var checkForResizeAttempt = false;
if (targetElement == rectTemplate)
{
//arr.push(cir ,cir1,rectTemplate)
dragTarget = targetElement;
checkForResizeAttempt = true;
var transMatrix = dragTarget.getCTM();
grabPoint.x = evt.clientX - Number(transMatrix.e);
grabPoint.y = evt.clientY - Number(transMatrix.f);
}
var transMatrix = dragTarget.getCTM();
//var transMatrix = dragTarget.getCTM().inverse();
grabPoint.x = evt.clientX - Number(transMatrix.e);
grabPoint.y = evt.clientY - Number(transMatrix.f);
if (window.console) console.log(grabPoint.x + " " + grabPoint.y);
if (window.console) console.log(evt.clientX + " " + evt.clientY);
if (checkForResizeAttempt)
{
clientPoint.x = evt.clientX;
clientPoint.y = evt.clientY;
rectX = Number(dragTarget.getAttributeNS(null, "x"));
rectY = Number(dragTarget.getAttributeNS(null, "y"));
rectWidth = Number(dragTarget.getAttributeNS(null, "width"));
rectHeight = Number(dragTarget.getAttributeNS(null, "height"));
if ((grabPoint.x - rectX) < 10)
{
resizingLeft = true;
}
else if (((rectX + rectWidth) - grabPoint.x) < 10)
{
resizingRight = true;
}
if (resizingLeft || resizingRight)
{
dragTarget.setAttributeNS(null,"stroke","green");
}
else
{
dragTarget.setAttributeNS(null,"stroke","black");
}
}
}
function MouseMove(evt)
{
evt.stopPropagation();
if (dragTarget == null)
{
return;
}
if (resizingLeft)
{
if (window.console) console.log(evt.clientX + " " + evt.clientY);
deltaX = (clientPoint.x - evt.clientX);
if (window.console) console.log("deltaX = " + deltaX);
dragTarget.setAttributeNS(null,"width",rectWidth + deltaX);
dragTarget.setAttributeNS(null,"x",rectX - deltaX);
}
else if (resizingRight)
{
deltaX = (clientPoint.x - evt.clientX);
if (window.console) console.log("rectWidth = " + rectWidth + " deltaX = " + deltaX);
dragTarget.setAttributeNS(null,"width",rectWidth - deltaX);
}
else
{
var newXX = evt.clientX-grabPoint.x;
var newYX = evt.clientY-grabPoint.y;
dragTarget.setAttributeNS(null,'transform','translate(' + newXX + ',' + newYX + ')');
}
}
function MouseUp(evt)
{
evt.stopPropagation();
if (dragTarget == null)
{
return;
}
resizingLeft = false;
resizingRight = false;
resizingTop = false;
resizingBottom = false;
// var transMatrix = dragTarget.getCTM().inverse();
dragTarget.setAttributeNS(null,"stroke","blue");
dragTarget = null;
}
</script>
</body>
</html>
--
=======SVG ====
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="612px" height="792px" xml:space="preserve"
onmousedown="ecmascript:top.MouseDown(evt)"
onmousemove="ecmascript:top.MouseMove(evt)"
onmouseup="ecmascript:top.MouseUp(evt)">
<g id="rect1">
<rect id="rectTemplate" x="0" y="0" stroke="blue" width="100" height="30" />
</g>
I have posted a sample of dragging and resizing transformed SVG rects in my answer here:
SVG coordinates with transform matrix
You can see the working example on my site here:
http://phrogz.net/svg/drag_under_transformation.xhtml
The key is to:
When you start dragging (mousedown) record the mouse location (in SVG global space).
During dragging (mousemove) calculate the offset (in SVG global space) for the drag, and then
Transform that offset from global space into the local space of the object, and use that to inform your changes.
This works regardless of the transformation hierarchy applied (as shown in my example).
Have you tried to change your code to rotate the shape around the center of the shape?
Here is an excerpt of the W3C draft on transform:
rotate(<rotate-angle> [<cx> <cy>]),
which specifies a rotation by <rotate-angle> degrees about a given point.
If optional parameters <cx> and <cy> are not supplied, the rotate is about the origin of the current user coordinate system.
The operation corresponds to the matrix [cos(a) sin(a) -sin(a) cos(a) 0 0].
If optional parameters <cx> and <cy> are supplied, the rotate is about the point (cx, cy).
The operation represents the equivalent of the following specification:
translate(<cx>, <cy>) rotate(<rotate-angle>) translate(-<cx>, -<cy>).
If you set cx and cy to the center of your ribbon, this may help from what context I can pick up from your code.