Creating a DataType that 'prints' property alias + node ID
Is there a way to create something like this?
That should open a popup window (a page I have created) to manage image maps. eg. /ManageImageMaps.aspx?nodeId=2891&alias=titleBanner
Could anyone think of a solution for that? I am familiar with Umbraco events, eg. Document.New - if that could be of any use...? Or perhaps using JavaScript?
Hi. You can easily get a current node id from within your field editor control with requesting HttpContext.Current.Request.QueryString["id"] since it's always passed to the parent content editor page in the url like "/umbraco/editContent.aspx?id=NNNN".
To open the standard umbraco popup dialog you can make use of the umbraco javascript function "UmbClientMgr.openModalWindow(...)" (you can look into the umbraco sources for the samples of its usage).
The simplest way of creating your own custom datatype is to make use of Umbraco Usercontrol Wrapper. All you will need is to add and implement a very simple interface (just one property) to a web user control and than you'll be able to use it as an umbraco custom datafild control. You can read quite a good manual how to do it with samples here: http://www.nibble.be/?p=24.
I have a problem that is partially related to that - suppose I have a datatype on a Membership Type that needs to know the NodeId of the member the particular instance is associated with. I can use the HttpContext if I am editing the member through the backend, but what if I have a custom control editing the member profile through a page in the front end. I can't rely on the HttpContext having the nodeId present; so what else can I use?
How exactly to you get to the editing control? Is this a logged-in member editing his/her own profile? Or is it an admin tool thtough which an admin can edit any member?
If it is a logged-in member editing his/her own profile, yiou should normally be able to get it's node ID through the Membership Provider, with something like this (code syntax not checked):
MemberhipUser member = Membership.GetUser(); string memberNodeId = member.ProviderUserKey.ToString();
It needs to be accessibly from any manner of situations - admin may have access to it on a custom form/page for example.
I solved it by injecting the member id into the datatype on a custom Member Event handler (Member.AfterSave). That way it doesn't matter where I access it from.
Do you really want to use the upload datatype or a custom fileupload which works the same as the upload datatype? For DAMP I sort of replicated the upload datatype. Have a look here: http://damp.codeplex.com/SourceControl/changeset/view/81602#1765786. In OnInit I add the upload control to a placeholder and in BtnCreate_Click I create a media item and actually use the upload datatype which is on the media type of the media item.
If you just want a fileupload control you can create media with this code:
public IDataType uploadField = new Factory().GetNewObject(new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"));
/// <summary>
/// Return the SqlHelper if we don't want to use OR/M.
/// </summary>
protected static ISqlHelper SqlHelper
{
get
{
return umbraco.BusinessLogic.Application.SqlHelper;
}
}
#region Insert - Methods
/// <summary>
/// Create a media item.
/// </summary>
/// <param name="parentId"></param>
/// <param name="name"></param>
/// <param name="fileName"></param>
/// <param name="mediaType"></param>
/// <param name="adminUser"></param>
/// <param name="bytes"></param>
/// <param name="isImage"></param>
/// <returns></returns>
public Media InsertMedia(int parentId, string fileName, MediaType mediaType, User adminUser, byte[] bytes, bool isImage)
{
Media media = Media.MakeNew(fileName, mediaType, adminUser, parentId);
string sql = string.Format(@"
select cpd.id as id from cmsPropertyData cpd
inner join cmsPropertyType cpt on cpd.propertytypeid = cpt.Id
inner join cmsDataType cdt on cpt.dataTypeId = cdt.nodeId
where cpd.contentNodeId = {0}
and cdt.controlId = '{1}'", media.Id, uploadField.Id);
int propertyId = SqlHelper.ExecuteScalar<int>(sql);
FileInfo file = new FileInfo(IOHelper.MapPath(SystemDirectories.Media + "/" + propertyId + "/" + fileName));
if (!file.Directory.Exists)
{
//If the directory doesn't exist then create it.
file.Directory.Create();
}
//Write the file to the media folder.
File.WriteAllBytes(file.FullName, bytes);
string umbracoFile = SystemDirectories.Media + "/" + propertyId.ToString() + "/" + fileName;
if (umbracoFile.StartsWith("~"))
{
umbracoFile = umbracoFile.TrimStart(new char[] { '~' });
}
if (media.getProperty("umbracoFile") != null)
{
media.getProperty("umbracoFile").Value = umbracoFile;
}
if (media.getProperty("umbracoExtension") != null)
{
media.getProperty("umbracoExtension").Value = Path.GetExtension(file.Name).Replace(".", string.Empty);
}
if (media.getProperty("umbracoBytes") != null)
{
media.getProperty("umbracoBytes").Value = bytes.Length;
}
if (isImage)
{
System.Drawing.Image image = System.Drawing.Image.FromFile(file.FullName);
if (media.getProperty("umbracoWidth") != null)
{
media.getProperty("umbracoWidth").Value = image.Width.ToString();
}
if (media.getProperty("umbracoHeight") != null)
{
media.getProperty("umbracoHeight").Value = image.Height.ToString();
}
//Create a thumbnail from the image.
string fileNameThumb = Path.Combine(file.Directory.FullName, file.Name.Replace(Path.GetExtension(file.Name), "_thumb.jpg"));
GenerateThumbnail(image, 100, image.Width, image.Height, fileNameThumb);
//Clean the image.
image.Dispose();
}
//Save the media file to update the xml and to make sure some event's get called.
media.Save();
media.XmlGenerate(new XmlDocument());
return media;
}
#endregion
#region Other - Methods
/// <summary>
/// Generate the thumbnail.
/// </summary>
/// <param name="image"></param>
/// <param name="maxWidthHeight"></param>
/// <param name="fileWidth"></param>
/// <param name="fileHeight"></param>
/// <param name="fullFilePath"></param>
/// <param name="ext"></param>
/// <param name="thumbnailFileName"></param>
private void GenerateThumbnail(System.Drawing.Image image, int maxWidthHeight, int fileWidth, int fileHeight, string thumbnailFileName)
{
//Generate thumbnail.
float fx = fileWidth / maxWidthHeight;
float fy = fileHeight / maxWidthHeight;
//Must fit in thumbnail size.
float f = Math.Max(fx, fy); if (f < 1) f = 1;
int widthTh = (int)(fileWidth / f); int heightTh = (int)(fileHeight / f);
//Create new image with best quality settings.
Bitmap bp = new Bitmap(widthTh, heightTh);
Graphics g = Graphics.FromImage(bp);
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
//Copy the old image to the new and resized.
Rectangle rect = new Rectangle(0, 0, widthTh, heightTh);
g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
//Copy metadata.
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo codec = null;
for (int i = 0; i < codecs.Length; i++)
{
if (codecs[i].MimeType.Equals("image/jpeg"))
codec = codecs[i];
}
//Set compresion ratio to 90%.
EncoderParameters ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L);
//Save the new image.
bp.Save(thumbnailFileName, codec, ep);
bp.Dispose();
g.Dispose();
}
#endregion
As a third option you can place the existing upload datatype on a usercontrol. For more info have a look at this:
Oh thank you so much Jeroen! This will really help me.
I haven't read all the code yet, but fyi I am trying to replicate the Upload field, adding image mapper functionality (see the screenshot on my question above).
So I probably want to use the existing upload control, but when saving into the database, save not only the filenames but also coordinates + href of the image maps.
Creating a DataType that 'prints' property alias + node ID
Is there a way to create something like this?
That should open a popup window (a page I have created) to manage image maps. eg. /ManageImageMaps.aspx?nodeId=2891&alias=titleBanner
Could anyone think of a solution for that?
I am familiar with Umbraco events, eg. Document.New - if that could be of any use...?
Or perhaps using JavaScript?
Thank you in advance.
Hi. You can easily get a current node id from within your field editor control with requesting HttpContext.Current.Request.QueryString["id"] since it's always passed to the parent content editor page in the url like "/umbraco/editContent.aspx?id=NNNN".
To open the standard umbraco popup dialog you can make use of the umbraco javascript function "UmbClientMgr.openModalWindow(...)" (you can look into the umbraco sources for the samples of its usage).
Thanks Rodion.
Any idea how to create a DataType that has the link and script?
The simplest way of creating your own custom datatype is to make use of Umbraco Usercontrol Wrapper. All you will need is to add and implement a very simple interface (just one property) to a web user control and than you'll be able to use it as an umbraco custom datafild control. You can read quite a good manual how to do it with samples here: http://www.nibble.be/?p=24.
I have a problem that is partially related to that - suppose I have a datatype on a Membership Type that needs to know the NodeId of the member the particular instance is associated with. I can use the HttpContext if I am editing the member through the backend, but what if I have a custom control editing the member profile through a page in the front end. I can't rely on the HttpContext having the nodeId present; so what else can I use?
Hi Robert,
How exactly to you get to the editing control? Is this a logged-in member editing his/her own profile? Or is it an admin tool thtough which an admin can edit any member?
If it is a logged-in member editing his/her own profile, yiou should normally be able to get it's node ID through the Membership Provider, with something like this (code syntax not checked):
Hope this helps.
Cheers,
Michael.
Here is an example which I use to get all the info of a member: http://our.umbraco.org/forum/developers/extending-umbraco/27626-Accessing-Member-Information
Jeroen
Hey guys,
It needs to be accessibly from any manner of situations - admin may have access to it on a custom form/page for example.
I solved it by injecting the member id into the datatype on a custom Member Event handler (Member.AfterSave). That way it doesn't matter where I access it from.
Thanks Rodion.
I am trying to replicate the Upload datatype. I have some problems, like getting a new media ID, or deleting the file when the node is deleted.
Is there a code I could copy or inherit from, or should I write it from scratch? And in either case, how? Anyone know?
Hi Hardy,
Do you really want to use the upload datatype or a custom fileupload which works the same as the upload datatype? For DAMP I sort of replicated the upload datatype. Have a look here: http://damp.codeplex.com/SourceControl/changeset/view/81602#1765786. In OnInit I add the upload control to a placeholder and in BtnCreate_Click I create a media item and actually use the upload datatype which is on the media type of the media item.
If you just want a fileupload control you can create media with this code:
As a third option you can place the existing upload datatype on a usercontrol. For more info have a look at this:
http://our.umbraco.org/forum/developers/extending-umbraco/6863-Datatype-on-normal-page-or-UserControl
http://our.umbraco.org/wiki/reference/code-snippets/use-mntp-on-a-usercontrol
Jeroen
Oh thank you so much Jeroen! This will really help me.
I haven't read all the code yet, but fyi I am trying to replicate the Upload field, adding image mapper functionality (see the screenshot on my question above).
So I probably want to use the existing upload control, but when saving into the database, save not only the filenames but also coordinates + href of the image maps.
I will look at your links, thanks a lot!
is working on a reply...