|
Hi
I am Sreedhar Ambati.
I downloaded the application and it is working fine in the same machine where it is deployed.
I created a virtual directory also.
If I am accessing the url from the same machine it is working fine.
But if I am accessing the url from another machine and doing any operation like "Add Post It" ,"Move the post" I am getting this warning message.
"this page is accessing information that is not under its control. this poses a security risk. Do you
want to continue" message.
If I press "Ok" the operation is performing.If clicked on NO then nothing is happening.
I enabled the IE browser Tools->Internet Options-> Security tab -> Internet.. Custom Level .. I enabled "Access data sources across domains" under miscellaneous.
Still the problem is not solved.
Thanks
Sreedhar Ambati
http://ambatisreedharworks.wordpress.com
Please tell me how to solve this problem.
sreedhar ambati
|
|
|
|
|
Hi, it's a very nice application...
I wanna integrate with in my application..
but 1 problem is there..
when I click on scrollbar some javascript error occurs with following function:
function findMoveable(e) {
if (e.moveable == 'true')//---------Error occurs here------------
return e;
if (e.tagName == "BODY")
return null;
return findMoveable(e.parentElement);
}
Can anybody solve this probs..
Thnx
|
|
|
|
|
Interesting. Which browser are you using?
|
|
|
|
|
|
Ah, that might have something to do with it. I've not tested it with IE7. I'll have to try it and get back to you. I've not noticed any problems with IE6, but something may have changed somewhere.
|
|
|
|
|
I think this is a fantastic little application. I can think of many uses for it – I for one would definitely be interested in a CMS implementation. I have tried adding it to an app of mine and I’m sure it will make a great addition. I tweaked the whole thing a bit so I can edit notes on a ‘per item’ basis. However, I haven’t got it working yet, as I don’t know how to update the RasieCallBackEvent after the initial page load…
…what I am trying to do is pass a (changing) reference to which item the notes relate to, to the RasieCallBackEvent – this reference I have added as an extra field in the db so it I can retrieve notes on a per item basis. Unfortunately, the RasieCallBackEvent does not update itself after a page call back and only uses the values on the initial page load. Basically, how do I refresh this method after a page call back so it acts like any other event-based method?
This is my first time using anything AJAX related, so I’m sure it’s my lack of understanding in that area that is holding me back.
Any ideas?
|
|
|
|
|
I'm not entirely sure what you mean, but it sounds sort of like what I was doing with this code originally. I'll run the scenario by you and see what you think. Originally this code was in a page that was data-driven, and the item in the database that was being viewed could be discerned from the querystring and a session variable (independently). Without sharing too much, if you imagine a directory of books, it was pretty much like that. Each book had an associated ID number (actually a guid in this instance, but whatever), and when you visited the page I had the notes on with a specific querystring, you got the details of the book it referred to. A consequence of this was that I could add another field to the database table for the notes (as you have done) to specify which "page" they appeared on. To hook it all together, for every event that alters or creates a note, I added a reference to the page (handily supplied by Request.QueryString["pageid"]) to the list of parameters for the AJAX function. When changes were written to the database, the "pageid" was written too, and it was therefore easy to see which notes pertained to which page. In actual fact, the postitid of the note and the pageid of the page form a sort of composite key, uniquely identifying a note in a page. Neither actually has to be unique on its own, as long as together they form a unique pair.
When the page is loaded, you need to alter the query that brings back the notes, so that you only include those notes that relate to the page you're viewing (again the QueryString comes in very handy here).
If this sounds vaguely like what you're after, let me know and I'll try to provide some concrete examples. It's very easy to do, but I can appreciate that it takes a bit of getting your head around.
|
|
|
|
|
I was trying to inject stuff here (sorry, I’ve redone it in vb):
Private Function RaiseCallbackEvent(ByVal eventArgument As String) As String
Dim booking_id = CInt(idLabel.Text) ' Get booking id from page
Dim args As String() = eventArgument.Split("~".ToCharArray())
Select Case (args(0))
Case "edit"
Note1.editNote(args(1), args(2), args(3))
Return "Note: " + args(1) + " TEXT: " + args(2)
Case "getid"
Dim newNote As Guid = Guid.NewGuid()
newNote = Note1.getNewNote(booking_id, "Anon")
Return newNote.ToString()
Case "move"
Note1.moveNote(args(1), Integer.Parse(args(2)), Integer.Parse(args(3)))
Return "Note: " + args(1) + " X: " + args(1) + " Y: " + args(3)
Case "delete"
Note1.deleteNote(args(1))
Return "Note: " + args(1) + " deleted!"
Case Else
Note1.resizeNote(args(1), Integer.Parse(args(2)), Integer.Parse(args(3)))
Return "Note: " + args(1) + " WIDTH: " + args(2) + " HEIGHT: " + args(3)
End Select
End Function
However, for some reason, booking_id never gets updated after a post back, like it would on a normal event, so this method doesn't work.
I do know what you mean about using the querystring. And have already come up with this solution, which - although I’ve just got it working - I didn’t think was the most elegant in the world. Here’s what I’ve done:
• Change the getNewNote function to accept an argument from the querystring:
Dim newNote As Guid = Guid.NewGuid()
newNote = Note1.getNewNote(args(1), "Anon") – anon is the author, another filed I added. --i've abstracted these out of support, so i didn't have to re-write the whole thing in vb
• Add some methods to Note.aspx.cs to access a variable wich stores the id to the div where the booking_id (or whatever your items might be) are stored:
private string id = "not_registered";
public void registerNewBookingDivID(string id_book)
{
id = id_book;
}
public string getDivID()
{
return id;
}
• Then change the createNote() javascript to get a handle on the div where the booking_id is stored:
function createNote() {
var cont=document.getElementById("NoteContainer");
var bookingValue = document.getElementById("<% Response.Write(this.getDivID());%>");
…..
Just make sure to call registerNewBookingDivID(string id_book) to tell the Note control where to pick the reference up from before a new note is created. It works, now notes are associated with booking, I just thought there would be a more elegant way. I’d be interested to see your solution.
Ben.
|
|
|
|
|
I'm not sure I'm understanding your method completely, but it looks like it might be a little more convoluted than it actually needs to be. I'll try to post some code examples later on today. I've got a deadline fast approaching, unfortunately, but my original application did include code to handle exactly this sort of scenario, so I should be able to extract some of it to show you.
|
|
|
|
|
Ok, these are the bits I think you'll need to change. I used the querystring, but if you've got tracking data (an id number or whatever) stored elsewhere, you can almost certainly use that instead, as long as the value is available when the notes are being manipulated.
<code>:::: C# ::::
string RaiseCallbackEvent(string eventArgument)
{
string[] args=eventArgument.Split("~".ToCharArray());
switch (args[1])
{
case "edit" :
Support.editPostit(args[0], args[2], args[3]);
return "Item: " + args[0] + " Postit: " + args[2] + " TEXT: " + args[3];
case "getid" :
Guid newpostit=new Guid();
newpostit=Support.getNewPostit(args[0]);
return newpostit.ToString();
case "move" :
Support.movePostit(args[0], args[2], int.Parse(args[3]), int.Parse(args[4]));
return "Item: " + args[0] + " Postit: " + args[2] + " X: " + args[3] + " Y: " +args[4];
case "delete" :
Support.deletePostit(args[0], args[2]);
return "Item: " + args[0] + " Postit: " + args[2] + " deleted!";
default :
Support.resizePostit(args[0], args[2], int.Parse(args[3]), int.Parse(args[4]));
return "Item: " + args[0] + " Postit: " + args[2] + " WIDTH: " + args[3] + " HEIGHT: " +args[4];
}
}
::::JAVASCRIPT::::
function DoCallback(url, params)
{
var pageUrl = url + "?callback=true&id=<% Response.Write(Request.QueryString["id"].ToString()); %>¶m=" + params;
var xmlRequest = createXMLHTTPObject();
xmlRequest.open("POST", pageUrl, false);
xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlRequest.send(null);
return xmlRequest;
}
function mouseup() {
var e=activeElement;
if (e!=null) {
e.style.zIndex=1;
if (doMove) {
var xmlRequest = DoCallback("http://<% Response.Write(System.Configuration.ConfigurationSettings.AppSettings["urlroot"]+this.Request.FilePath);%>", '<% Response.Write(Request.QueryString["id"].ToString()); %>~move~'+e.id+'~'+e.style.posLeft+'~'+e.style.posTop);
} else {
var xmlRequest = DoCallback("http://<% Response.Write(System.Configuration.ConfigurationSettings.AppSettings["urlroot"]+this.Request.FilePath);%>", '<% Response.Write(Request.QueryString["id"].ToString()); %>~resize~'+e.id+'~'+e.style.posWidth+'~'+e.style.posHeight);
}
doMove = true;
doResize = false;
}
}
function createPostit() {
var cont=document.getElementById("postitcontainer");
var xmlRequest = DoCallback("http://<% Response.Write(System.Configuration.ConfigurationSettings.AppSettings["urlroot"]+this.Request.FilePath);%>", '<% Response.Write(Request.QueryString["id"].ToString()); %>~getid');
cont.innerHTML+="<div id=\""+xmlRequest.responseText+"\" moveable=true style=\"cursor: hand; position: absolute; top: 150px; left: 100px; width: 100px; height: 100px; background-color: #ffffdd; border: solid 1px black\"><div contenteditable style=\"cursor:text; font-family: arial; margin-bottom: 12px;\">Click and drag me</div><span style=\"position: absolute; bottom: 0px; left: 1px; font-family: arial;\"><a href=\"javascript:void(0);\" onclick=\"setText()\">save</a> <a href=\"javascript:void(0);\" onclick=\"deletePostit()\">delete</a></span><span style=\"cursor:nw-resize;\"><img src=\"Images/corner.gif\" contenteditable=false unselectable=on style=\"position: absolute; right: 0px; bottom: 0px;\" id=\"anchor\" /></span></div>";
document.onmouseup=mouseup;
document.onmousedown = mousedown;
document.onmousemove = mousemove;
document.onselectstart = rfalse;
}
function setText() {
var e=activeElement;
e.style.zIndex=1;
var content=e.firstChild;
var xmlRequest = DoCallback("http://<% Response.Write(System.Configuration.ConfigurationSettings.AppSettings["urlroot"]+this.Request.FilePath);%>", '<% Response.Write(Request.QueryString["id"].ToString()); %>~edit~'+e.id+'~'+content.innerHTML);
}
function deletePostit() {
var e=activeElement;
e.style.display="none";
var xmlRequest = DoCallback("http://<% Response.Write(System.Configuration.ConfigurationSettings.AppSettings["urlroot"]+this.Request.FilePath);%>", '<% Response.Write(Request.QueryString["id"].ToString()); %>~delete~'+e.id);
}
:::: Embedded in Note.ascx ::::
<div id="postitcontainer">
<% Response.Write(StickyNotes.Support.getOldPostits(Request.QueryString["id"].ToString())); %>
</div></code>
|
|
|
|
|
Some stuff in the above listing seems to have broken, but it should give you the general idea.
|
|
|
|
|
Hi,
Thanks for the reply. That is a good solution (just one point, aren’t you adding the id twice if it’s in doCallBack() and all the other functions?) but I still don’t think it would work in my scenario. My biggest problem is the value for the id the notes are attached to is not available at page load. It also changes during the life of the page and I want the associated notes to change with it. It’s actually from the id of a record from a details view and as I page through the records, I want the connected set of notes to change.
Creating, saving and deleting notes using this process is fairly easy. I found the difficulty is in retrieving the old notes that only pertain to the record on the current page of the detialsview.
To create records,I altered the database and stored procedures etc. to account for the extra field, then added a variable in the code behind page of the Note user control which contained a reference to the DOM element that contained the changing value of the id in question. Part of initialising the page containg the notes control, is then to tell it where this changing id value is (rather than get it from the detailsview it’s easier to pass it to a hidden label for reference) so, something like:
private void Page_Load(object sender, System.EventArgs e)
{
Note1.registerNewBookingDivID(idLabel.ClientID)
}
(clientID gives you the id of the control rendered on the page)
Then when creating a new element, get a handle on changing id in the javascript like this:
function createNote() {
var cont=document.getElementById("NoteContainer");
var bookingValue = document.getElementById("<% Response.Write(this.getDivID());%>");
if(bookingValue.id!="not_registered"){
var xmlRequest = DoCallback("<% Response.Write(Request.Url.ToString());%>", 'getid~'+bookingValue.innerHTML);
etc..}
Now, the new note is associated with a certain id and I can edit, save and delete it. That isn’t much of a problem...More tricky was getting a handle on old notes, by id, as I page through the details view.
I’ve done it by adding another variable to the Note control, that contains the actual value of the booking id. This is similar to above, only now, we have to call this every time the id changes. Because my detailsview changes according to a calendar control, I actually did this on the calendar selection changed event:
Private voidCalendar1_SelectionChanged(Object sender ,System.EventArgs e)
{
Note1.registerBookingID(CInt(idLabel.Text))
}
Then call the old notes only relating the current id in the NoteContainer div like so:
<% Response.Write(StickyNotes.Support.getOldNotes(this.getCurrentBookingID())); %>
There was a bit more tweaking to be done, but I have now essentially got the sytem working the way I want.
One other change I made is to use,
"<%Response.Write(Request.Url.ToString());%>"
Instead of,
"http://<% Response.Write(System.Configuration.ConfigurationSettings.AppSettings["urlroot"]+this.Request.FilePath);%>"
It just saves having to change web.config at all.
As far as I’m aware, you cannot change the querystring programatically during a page postback, so, although a easier, I don’t think your method would have worked.
|
|
|
|
|
No, you're right, and I misunderstood what you were after. And I take on board your comment about Request.Url.ToString(), that is much easier. Just goes to show how you can get stuck in one inefficient way of doing things if you don't keep looking. Thanks for that, it's so simple, I don't know why it never occurred to me (except that I already knew a way to handle url paths and a way to get the current server from the config settings and smushed them together rather than look for something cleverer!).
And yes, I am sending the QueryString stuff twice, I got carried away...
That'll teach me to post stuff in a hurry
Thanks for giving me your solution. It may not be the most elegant way to do it, but if not I certainly can't think of a better way, now that I understand what you're doing. I'm impressed. I think the great thing about codeproject is that it allows stuff like this to happen. You can actually learn more about your own code, as well as other people's, by posting it here.
|
|
|
|
|
I've solved some of the cross-platform issues. The code now runs in Opera as well as IE, but Firefox remains stubborn (and rightly so, really, it's my code that isn't quite following the standards). I've also discovered a bug that I didn't spot first time around. To see it, drag a note around a bit, then click anywhere else on the page and drag the mouse around a bit... See what I mean? That's not right, is it? To fix it, simply add an else clause to the mousedown event where we do "if (mp)". Set activeElement to null there and all will be hunky-dory. The issue is simple and I should have spotted it before. If you don't click in a different note, activeElement is never reset and still relates to the last note you clicked.
I'll be releasing the new code once I've cracked Firefox. I'm not getting much time to play with this code at present, because it's no longer what I'm supposed to be actively working on, but I'll try to get it out asap.
I'm also considering building it into something approaching a rudimentary, totally free-form CMS type application. You build your page with floating divs, add images and whatnot, and then save the current state of the page to a static file (or database entry, more likely). Any interest?
|
|
|
|
|
Hi,
When i looked at ur annotation tool,i felt some what relaxed as i have been trying to annotate text in web page.I have searched for this on web but none had reached to the scope of my application.
I didn't get the idea of using Ajax regarding this.Always i have tried using only DHTML.
I have one issue regarding the shape of note u used i.e (square shape).
can't we place a polygon instead which often we see in websites indicating annotation to images,text.
And can't we use Client callback concept for getting the annotated text.
-- modified at 10:18 Saturday 14th October, 2006
kamalnath
|
|
|
|
|
Indeed, you could do both of these things. I suppose the best way to implement a polygon shaped note would be to use a background image on the div rather than just a background colour and border. This is not hard to do and it would also be perfectly possible to make such a shape scale (as long as the portion containing the text remained rectangular).
As for getting the text via a callback, this can also be done, but as I wanted the text to appear when the page was loaded I didn't see much point implementing it via a callback, it was much simpler to just use regular ASP.NET concepts. If you wanted to use a callback to do it, it's simple enough to do, just attach an onload event to your page and create a callback routine similar to the existing ones that fetches the text of the appropriate div.
|
|
|
|
|
Great project, it verily gives a extra dimension to "User Experience". I just had a quick look at it fell in love with it at once
First a couple of questions:
There isn't any User Registration, that means that every one hoe come to that page can se my notes?
Have you consider using a cookie on the client side to save the notes in? and why not?
Remarks:
As far as I can se it only work with IE and not with FireFox and Flock.
If you use "Enter" to create a new paragraph inside a note. He don't save what’s coming after the first Enter
Anders
NetAnders.Org
|
|
|
|
|
Thanks for your comments!
I think an important thing to bear in mind here is that this code was literally taken straight from an app I'm in the process of writing, so it has certain features that might not be immediately comprehensible.
There's no user registration because in the context of the app, the user who posted the note is irrelevant, by all means add user registration to it, it should be extremely simple.
Again, in the context of the app, cookies wouldn't do the job. The purpose of the notes in the app I'm writing is to allow superusers to annotate pages within the app, so that ordinary users can see the annotations. When ordinary users view the pages with notes, they don't get the opportunity to move them around, delete them or modify them in any way, as far as they're concerned the notes are a static part of the page, only the superuser can annotate pages.
As it stands it will only work with IE. This is something I hope to fix, as I've mentioned in another comment, but again, for the purposes of the app I'm writing, IE is the only supported target anyway. We don't deploy anything else across our intranet and while I try to write cross browser/cross platform code as a matter of course, sometimes in this environment it's better to cut and run with something that works in IE, because no one's ever going to run it in anything else anyway. The comment has been taken on board however, and I'll try to spend some time working out the cross browser issues.
I'm not sure about your last point. I've had no problem getting it to store notes over multiple paragraphs, but I think it will depend on how long the note is. Because the data is passed in the querystring there's a limit to the amount of text it will take. Admittedly I ought to have enforced this, but the limit is sufficiently large for most practical applications I wanted to put it to. Again, this is something that should possibly be looked at. If I can find a way of altering the code to use a different transfer method that would be great. I thought of building a POST request, complete with form data instead of a GET, but GET was much easier and fitted my requirements.
As ever, this code is really just an example of what can be done, feel free to use it as a template and write your own solution around it.
|
|
|
|
|
I have not gone through your code, but I think you could use this to return you a XMLHTTP object that will work with the browser used. I don't know this will break your code any where ells?
<br />
function createXMLHTTPObject ()<br />
{<br />
var xmlhttp;<br />
try {<br />
xmlhttp=new ActiveXObject("Msxml2.XMLHTTP")<br />
} catch (e) {<br />
try {<br />
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")<br />
} catch (e) {<br />
xmlhttp=false<br />
}<br />
}<br />
if (!xmlhttp) {<br />
try {<br />
xmlhttp = new XMLHttpRequest();<br />
} catch (e) {<br />
xmlhttp=false;<br />
}<br />
}<br />
return xmlhttp;<br />
}<br />
For the question - "Not saving Text after a Enter'".
If I create a note and type in something direct after the "Click and Drag Me" it save the text perfectly. But do I hit enter and type in some more text - then save it. It would not save the latest added text. Do I close the browser and open the page in a new browser the latest text isn't there.
Anders
NetAnders.org
|
|
|
|
|
I tried something similar to that, but it didn't seem to want to work with the way I'd set everything up. I'll take another look at it though.
I'll take a look at the issue you mention too. I've not seen this happen here, but if it's something I can duplicate then I'll definitely take a shot at fixing it.
Thanks.
|
|
|
|
|
I've looked into the cross browser aspects, and mostly it's the drag and resize code that causes problems. It seems possible to do the ajax stuff cross platform (not sure what was going wrong when I tried it last time, but your function certainly makes it work ok). The script currently relies on IE's event model. In order to make it work cross platform I need to account for other event models which is going to mean quite a lot of minor code changes. I'll do these soon and test the results, if it all works I'll make the revisions available here.
|
|
|
|
|
Thanks - That would be very nice
|
|
|
|
|
I've got it working in Opera now, but Firefox still doesn't want to play. If I get some inspiration later, hopefully I'll fix it, but at least what I've got now works in more than one browser.
I'll hold off on updating the code until I've got something that works in Firefox, since I guess more people will be interested in that than in the fix for Opera.
|
|
|
|
|
Is it cross-browser? Does it use any ajax libraries?
it's a very nice example, but I know it may be a nightmare to make it work on all different browsers and with different settings. I guess it requires scripting enabled on the client, but what else? Will it work with IE security settings set to "internet zone"?
It would be best to have an online example to test, if possible, thank you.
|
|
|
|
|
It doesn't use any ajax libraries, there are no requirements other than the ability to compile the project, a web server to put it on and suitable browser to view it with.
Unfortunately at the moment it's not cross browser compatible. It uses the MS ActiveX control to do the ajax stuff, as the application I stripped it out of is one I'm developing for my work's intranet and browsers other than IE aren't even deployed in this environment, much less supported (more's the pity, I say). I did try to make it cross browser, because frankly short sightedness like only supporting IE annoys me, but I couldn't find a way to get it to work the same way everywhere. I'll keep looking though.
It works fine with security set to "Internet Zone".
Currently, the only web-facing server I have is a linux box that doesn't (obviously) run .NET code. At some point I will be putting mono on it and attempting ti change all that, but for now I've got nowhere to host sample apps, I'm afraid.
|
|
|
|
|