{"id":4821,"date":"2017-12-04T08:00:31","date_gmt":"2017-12-04T08:00:31","guid":{"rendered":"http:\/\/a1webdesignteam.com\/blog\/?p=4821"},"modified":"2017-12-04T08:00:31","modified_gmt":"2017-12-04T08:00:31","slug":"facebook-style-photo-tag","status":"publish","type":"post","link":"https:\/\/a1webdesignteam.com\/blog\/facebook-style-photo-tag\/","title":{"rendered":"Facebook Style Photo Tag"},"content":{"rendered":"<ul class=\"download\">\n<li><a href=\"https:\/\/www.codeproject.com\/KB\/aspnet\/Facebook_Style_Photo_Tag\/fbPhotoTag.zip\">Download source &#8211; 1.66 MB<\/a><\/li>\n<\/ul>\n<h2>Introduction<\/h2>\n<p>You know how in <a href=\"http:\/\/www.facebook.com\/\">Facebook<\/a>, you can <strong>Tag <\/strong>images like this:<\/p>\n<p><img loading=\"lazy\" src=\"https:\/\/www.codeproject.com\/KB\/aspnet\/Facebook_Style_Photo_Tag\/fbTag.jpg\" alt=\"fbTag.jpg\" width=\"640\" height=\"354\" border=\"0\" hspace=\"0\" \/><\/p>\n<p>How can this be done in .NET ?<\/p>\n<h2>BreakDown<\/h2>\n<p>We&#8217;ll have to divide this feature into a number of components:<\/p>\n<ol>\n<li>Select an area<\/li>\n<li>A list of friends is shown<\/li>\n<li>After selecting a friend, a label with friends name is added<\/li>\n<li>Friend name is removed from list (step 2)<\/li>\n<li>Image is now marked with the friends name where you selected<\/li>\n<li>On hovering the label with friend name, area from step(1) is selected<\/li>\n<\/ol>\n<p>For steps (1) and (6), we will use <strong>Michal Wojciechowski<\/strong>&#8216;s <em>imgAreaSelect<\/em>.<\/p>\n<p>We&#8217;ll get into that shortly, first let&#8217;s examine the database.<\/p>\n<h2>ERD<\/h2>\n<p><img loading=\"lazy\" src=\"https:\/\/www.codeproject.com\/KB\/aspnet\/Facebook_Style_Photo_Tag\/ERD.jpg\" alt=\"ERD.jpg\" width=\"640\" height=\"188\" border=\"0\" hspace=\"0\" \/><\/p>\n<h4><img loading=\"lazy\" src=\"https:\/\/www.codeproject.com\/KB\/aspnet\/Facebook_Style_Photo_Tag\/vTags.jpg\" alt=\"vTags.jpg\" width=\"198\" height=\"156\" \/><\/h4>\n<h4>tPhoto<\/h4>\n<p>Nothing special here, holds the photo name, id and path.<\/p>\n<h4>tFriend<\/h4>\n<p>we need a boolean to tell us whether the friend has been tagged already or not, so he won&#8217;t be shown again in the list (step number 2).<\/p>\n<h4>tTag<\/h4>\n<p>Holds the data about areas <strong>position<\/strong> in the photo, and <strong>Id<\/strong> of tagged person.<\/p>\n<p><em>In real life the tables are more complex, where a friend can be tagged in more than one photo and a photo can have more than one friend tagged, this is simplified for the sake of demonstration.<\/em><\/p>\n<p><strong>vTag<\/strong><br \/>\nThe view displaying the tagged friends, the special field here is <strong>Coords<\/strong>, which is areas&#8217; positions(from <strong>tTag,x1,y1,x2,y2<\/strong>)\u00a0concatenated together\u00a0,we&#8217;ll need that later<\/p>\n<h2>How to Use the Code<\/h2>\n<p>This is the JavaScript function <code>imgAreaSelect()<\/code>, notice it&#8217;s bound to our <code>asp:Image <\/code>control, <code>Image1<\/code>, it magically frames the area we selected based on image name.<\/p>\n<p>our image control name in\u00a0run-time\u00a0is <code>MainContent_Image1<\/code>\u00a0,\u00a0that&#8217;s\u00a0the one we&#8217;ll use.<\/p>\n<div id=\"premain743711\" class=\"pre-action-link\"><span id=\"prehide743711\">Hide<\/span> \u00a0 <span id=\"copycode743711\">Copy Code<\/span><\/div>\n<pre id=\"pre743711\" class=\"notranslate\" lang=\"jscript\">$(<span class=\"code-keyword\">function<\/span> () {\r\n            $(<span class=\"code-string\">'<\/span><span class=\"code-string\">#MainContent_Image1'<\/span>).imgAreaSelect({ aspectRatio: <span class=\"code-string\">'<\/span><span class=\"code-string\">1:1'<\/span>, handles: <span class=\"code-keyword\">true<\/span>,\r\n                fadeSpeed: <span class=\"code-digit\">200<\/span>, onSelectChange: Select, onSelectEnd: DisplayFriends\r\n            });\r\n        });<\/pre>\n<p>We have 4 hidden fields in the page, we need those to store the positions of area selected.<\/p>\n<p>Now, this function fires the <code>onSelectEnd<\/code> event, which calls the function <code>Select()<\/code>, it simply populates the hidden fields.<\/p>\n<div id=\"premain88327\" class=\"pre-action-link\"><span id=\"prehide88327\">Hide<\/span> \u00a0 <span id=\"copycode88327\">Copy Code<\/span><\/div>\n<pre id=\"pre88327\" class=\"notranslate\" lang=\"jscript\"><span class=\"code-keyword\">function<\/span> Select(img, selection) {\r\n<span class=\"code-keyword\">if<\/span> (!selection.width || !selection.height)\r\n<span class=\"code-keyword\">return<\/span>;\r\ndocument.getElementById(<span class=\"code-string\">'<\/span><span class=\"code-string\">&lt;%=x1.ClientID %&gt;'<\/span>).value = selection.x1;\r\ndocument.getElementById(<span class=\"code-string\">'<\/span><span class=\"code-string\">&lt;%=y1.ClientID %&gt;'<\/span>).value = selection.y1;\r\ndocument.getElementById(<span class=\"code-string\">'<\/span><span class=\"code-string\">&lt;%=x2.ClientID %&gt;'<\/span>).value = selection.x2;\r\ndocument.getElementById(<span class=\"code-string\">'<\/span><span class=\"code-string\">&lt;%=y2.ClientID %&gt;'<\/span>).value = selection.y2;\r\n}<\/pre>\n<p>&#8230; and on the <code>onSelectEnd<\/code> event, we&#8217;ll call our <code>DisplayFriends()<\/code> method.<\/p>\n<p><code>dvFriends<\/code> is a <strong>div<\/strong> containing a <code>datalist<\/code> populated with our untagged friends <em>(initially hidden of course)<\/em>.<\/p>\n<div id=\"premain22537\" class=\"pre-action-link\"><span id=\"prehide22537\">Hide<\/span> \u00a0 <span id=\"copycode22537\">Copy Code<\/span><\/div>\n<pre id=\"pre22537\" class=\"notranslate\" lang=\"jscript\"><span class=\"code-keyword\">function<\/span> DisplayFriends(img, selection) {\r\n<span class=\"code-keyword\">if<\/span> (!selection.width || !selection.height || \r\n\tdocument.getElementById(<span class=\"code-string\">'<\/span><span class=\"code-string\">&lt;%=HFShowFriends.ClientID %&gt;'<\/span>).value == <span class=\"code-string\">\"<\/span><span class=\"code-string\">0\"<\/span>)\r\n<span class=\"code-keyword\">return<\/span>;\r\ndocument.getElementById(<span class=\"code-string\">'<\/span><span class=\"code-string\">&lt;%=dvFriends.ClientID %&gt;'<\/span>).style.display = <span class=\"code-string\">\"<\/span><span class=\"code-string\">block\"<\/span>;\r\n}<\/pre>\n<p>When user selects a friend, it will fire the function <code>SelectEnd()<\/code> which ends the selection process.<\/p>\n<div id=\"premain437236\" class=\"pre-action-link\"><span id=\"prehide437236\">Hide<\/span> \u00a0 <span id=\"copycode437236\">Copy Code<\/span><\/div>\n<pre id=\"pre437236\" class=\"notranslate\" lang=\"jscript\"><span class=\"code-keyword\">function<\/span> SelectEnd() {\r\n$(<span class=\"code-string\">'<\/span><span class=\"code-string\">#MainContent_Image1'<\/span>).imgAreaSelect({ hide: <span class=\"code-keyword\">true<\/span> });\r\n}<\/pre>\n<p>Nice, now we need to actually <strong>tag<\/strong> the image <em>(where you hover on photo and see a tool tip displaying the friend&#8217;s name).<\/em><\/p>\n<p>To do this, we&#8217;ll use an <a href=\"http:\/\/www.w3schools.com\/TAGS\/tag_map.asp\">HTML map<\/a>.<\/p>\n<p><code>AddNewArea()<\/code> function takes the newly created <code>tTag<\/code> object and adds a new <strong>area<\/strong> to the <strong>map<\/strong>.<\/p>\n<div id=\"premain743854\" class=\"pre-action-link\"><span id=\"prehide743854\">Hide<\/span> \u00a0 <span id=\"copycode743854\">Copy Code<\/span><\/div>\n<pre id=\"pre743854\" class=\"notranslate\" lang=\"cs\"><span class=\"code-keyword\">private<\/span> <span class=\"code-keyword\">void<\/span> AddNewArea(tTag t)\r\n{\r\n    HtmlGenericControl gcArea = <span class=\"code-keyword\">new<\/span> HtmlGenericControl(<span class=\"code-string\">\"<\/span><span class=\"code-string\">area\"<\/span>);\r\n    gcArea.Attributes.Add(<span class=\"code-string\">\"<\/span><span class=\"code-string\">shape\"<\/span>, <span class=\"code-string\">\"<\/span><span class=\"code-string\">rect\"<\/span>);\r\n    gcArea.Attributes.Add(<span class=\"code-string\">\"<\/span><span class=\"code-string\">href\"<\/span>, <span class=\"code-string\">\"<\/span><span class=\"code-string\">#\"<\/span>);\r\n    <span class=\"code-keyword\">string<\/span> strFriendName = Friends.GetFriendName(t.nFriendId);\r\n    gcArea.Attributes.Add(<span class=\"code-string\">\"<\/span><span class=\"code-string\">id\"<\/span>, <span class=\"code-string\">\"<\/span><span class=\"code-string\">a\"<\/span> + t.nFriendId.ToString());\r\n    gcArea.Attributes.Add(<span class=\"code-string\">\"<\/span><span class=\"code-string\">title\"<\/span>, strFriendName);\r\n    gcArea.Attributes.Add(<span class=\"code-string\">\"<\/span><span class=\"code-string\">alt\"<\/span>, strFriendName);\r\n    gcArea.Attributes.Add(<span class=\"code-string\">\"<\/span><span class=\"code-string\">coords\"<\/span>, GenerateCoordiantes(t));\r\n    mapPhoto.Controls.Add(gcArea);\r\n}<\/pre>\n<p><em>(<strong>Note<\/strong>: In case of using <strong>Mozilla Firefox 5.0<\/strong> or <strong>Safari 5.0.3<\/strong>, the tagging effect does not work until after refreshing the whole page.)<\/em><\/p>\n<p>Very good, now we need the area to be selected again on hovering the links, which are actually <code>ItemTemplates<\/code> inside a <code>datalist.<\/code><\/p>\n<div id=\"premain593684\" class=\"pre-action-link\"><span id=\"prehide593684\">Hide<\/span> \u00a0 <span id=\"copycode593684\">Copy Code<\/span><\/div>\n<pre id=\"pre593684\" class=\"notranslate\" lang=\"aspnet\"><span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">asp:DataList<\/span> <span class=\"code-attribute\">ID<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">dlTaggedFriends\"<\/span> <span class=\"code-attribute\">runat<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">server\"<\/span> <span class=\"code-attribute\">RepeatDirection<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">Horizontal\"<\/span> \r\n\r\n<span class=\"code-attribute\">DataSourceID<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">sdsTags\"<\/span>\r\n\r\n<span class=\"code-attribute\">ViewStateMode<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">Disabled\"<\/span><span class=\"code-keyword\">&gt;<\/span>\r\n<span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">ItemTemplate<\/span><span class=\"code-keyword\">&gt;<\/span>\r\n<span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">asp:LinkButton<\/span> <span class=\"code-attribute\">ID<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">lbName\"<\/span> <span class=\"code-attribute\">runat<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">server\"<\/span> <span class=\"code-attribute\">onmouseout<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">SelectEnd()\"<\/span> \r\n\r\n<span class=\"code-attribute\">onmouseover<\/span><span class=\"code-keyword\">='<\/span><span class=\"code-keyword\"><span class=\"code-pagedirective\">&lt;%<\/span>#Eval(<span class=\"code-string\">\"<\/span><span class=\"code-string\">Coords\"<\/span>,<span class=\"code-string\">\"<\/span><span class=\"code-string\">preview(\\\"{0}\\\");\"<\/span>)<span class=\"code-pagedirective\">%&gt;<\/span>'<\/span>\r\n\r\n<span class=\"code-attribute\">Text<\/span><span class=\"code-keyword\">='<\/span><span class=\"code-keyword\"><span class=\"code-pagedirective\">&lt;%<\/span># Eval(<span class=\"code-string\">\"<\/span><span class=\"code-string\">sName\"<\/span>) <span class=\"code-pagedirective\">%&gt;<\/span>'<\/span><span class=\"code-keyword\">&gt;<\/span><span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">\/asp:LinkButton<\/span><span class=\"code-keyword\">&gt;<\/span>\r\n(<span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">asp:LinkButton<\/span> <span class=\"code-attribute\">ID<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">lbRemoveTag\"<\/span> <span class=\"code-attribute\">runat<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">server\"<\/span> \r\n\r\n<span class=\"code-attribute\">CommandArgument<\/span><span class=\"code-keyword\">='<\/span><span class=\"code-keyword\"><span class=\"code-pagedirective\">&lt;%<\/span># Eval(<span class=\"code-string\">\"<\/span><span class=\"code-string\">nFriendId\"<\/span>) <span class=\"code-pagedirective\">%&gt;<\/span>'<\/span>\r\n\r\n<span class=\"code-attribute\">OnCommand<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">lbRemoveTag_Command1\"<\/span><span class=\"code-keyword\">&gt;<\/span>remove<span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">\/asp:LinkButton<\/span><span class=\"code-keyword\">&gt;<\/span>)\r\n<span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">asp:Literal<\/span> <span class=\"code-attribute\">ID<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">Literal1\"<\/span> <span class=\"code-attribute\">runat<\/span><span class=\"code-keyword\">=\"<\/span><span class=\"code-keyword\">server\"<\/span><span class=\"code-keyword\">&gt;<\/span><span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">\/asp:Literal<\/span><span class=\"code-keyword\">&gt;<\/span>\r\n<span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">\/ItemTemplate<\/span><span class=\"code-keyword\">&gt;<\/span>\r\n<span class=\"code-keyword\">&lt;<\/span><span class=\"code-leadattribute\">\/asp:DataList<\/span><span class=\"code-keyword\">&gt;<\/span><\/pre>\n<p>The DatasourceId of\u00a0datalist\u00a0<span class=\"Apple-style-span\">dlTaggedFriends<\/span>\u00a0, is SqlDataSource\u00a0<span class=\"Apple-style-span\"><code>sdsTags<\/code><\/span>\u00a0,\u00a0which is bound to the view\u00a0<code>&lt;span class=\"Apple-style-span\" style=\"font-size: 15px; line-height: normal; \"&gt;vTag&lt;\/span&gt;\u00a0\u00a0<\/code><\/p>\n<p><img loading=\"lazy\" src=\"https:\/\/www.codeproject.com\/KB\/aspnet\/Facebook_Style_Photo_Tag\/vTagsData.jpg\" alt=\"vTagsData.jpg\" width=\"376\" height=\"87\" \/><\/p>\n<p>That&#8217;s why we concatenated the\u00a0positions, to pass them as one parameter to the javascript function\u00a0\u00a0<span class=\"Apple-style-span\">preview()<\/span>\u00a0on\u00a0\u00a0<code>onmouseover<\/code>\u00a0event, where they&#8217;ll be\u00a0spitted\u00a0again\u00a0.<\/p>\n<div id=\"premain727142\" class=\"pre-action-link\"><span id=\"prehide727142\">Hide<\/span> \u00a0 <span id=\"copycode727142\">Copy Code<\/span><\/div>\n<pre id=\"pre727142\" class=\"notranslate\" lang=\"jscript\"><span class=\"code-keyword\">function<\/span> preview(Coords) {\r\n            <span class=\"code-keyword\">var<\/span> arrResult = Coords.split(<span class=\"code-string\">\"<\/span><span class=\"code-string\">,\"<\/span>);\r\n            <span class=\"code-keyword\">var<\/span> nx1 = arrResult[<span class=\"code-digit\">0<\/span>];\r\n            <span class=\"code-keyword\">var<\/span> ny1 = arrResult[<span class=\"code-digit\">1<\/span>];\r\n            <span class=\"code-keyword\">var<\/span> nx2 = arrResult[<span class=\"code-digit\">2<\/span>];\r\n            <span class=\"code-keyword\">var<\/span> ny2 = arrResult[<span class=\"code-digit\">3<\/span>];\r\n            <span class=\"code-keyword\">var<\/span> ias = $(<span class=\"code-string\">'<\/span><span class=\"code-string\">#MainContent_Image1'<\/span>).imgAreaSelect({ instance: <span class=\"code-keyword\">true<\/span> });\r\n            ias.setSelection(nx1, ny1, nx2, ny2, <span class=\"code-keyword\">true<\/span>);\r\n            ias.setOptions({ show: <span class=\"code-keyword\">true<\/span> });\r\n            ias.update();\r\n}<\/pre>\n<h2>Output<\/h2>\n<p><img loading=\"lazy\" src=\"https:\/\/www.codeproject.com\/KB\/aspnet\/Facebook_Style_Photo_Tag\/Example.jpg\" alt=\"Example.jpg\" width=\"464\" height=\"394\" border=\"0\" hspace=\"0\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Download source &#8211; 1.66 MB Introduction You know how in Facebook, you can Tag images like this: How can this be done in .NET ? BreakDown We&#8217;ll have to divide this feature into a number of components: Select an area A list of friends is shown After selecting a friend, a label with friends name [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4823,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0},"categories":[32],"tags":[135,136,51,119,137],"_links":{"self":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts\/4821"}],"collection":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/comments?post=4821"}],"version-history":[{"count":0,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts\/4821\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/media\/4823"}],"wp:attachment":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/media?parent=4821"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/categories?post=4821"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/tags?post=4821"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}