ScriptManager in MasterPage

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • krungkrung
    New Member
    • Nov 2008
    • 18

    ScriptManager in MasterPage

    Hi all,

    Can somebody help me figure out whats wrong with my program?

    I created a site with the use of MasterPage..and with a plan of utilizing and abusing the capabilities of AJAX, I added the ScriptManager to create PageMethods.

    Here's what I did:

    1. I added the "ScriptMana ger" and the "JavaScript that calls the page method" in MasterPage...wi th Javascript inside the <body> tag and ScriptManager inside the <form> tag.

    2. In the "Child Form", I created a HTML image component, and in the OnClick event it calls the JavaScript function which calls the PageMethod.


    When I run the page it doesnt display any errors at all, but everytime I click the image component(which triggers the javascript func)..it displays "Error on page" at the bottom left side of the page and the desired output don't display.

    You might be thinking that the error could be on the code(which probably true), but I tried the same code without using a MasterPage and it works without any error.

    Any suggestion and advice will be very much appreciated. Thanks.
  • Frinavale
    Recognized Expert Expert
    • Oct 2006
    • 9749

    #2
    It is very likely that this is a JavScript error.
    You could use IE8 or FireFox's FireBug tool to debug the error.

    -Frinny

    Comment

    • krungkrung
      New Member
      • Nov 2008
      • 18

      #3
      Hi Frinny!

      Thanks for the reply.

      Yeah I agree with you that it is very likely a JavaScript error. But why is it that, when I run the page in a single page(without using the MasterPage) and using the same JavaScript function, It executes smoothly? Isn't the error also something to do with 'ScriptManager' being placed in the MasterPage or something to that effect?

      Btw, I placed the PageMethods inside a Base Class which inherits the System.Web.UI.P age and all pages inherits that Base Class. (I did this as it was mentioned in the other forum that PageMethods should be placed inside a BaseClass when using MasterPage)

      Thanks.

      Comment

      • sudevg
        New Member
        • Jul 2009
        • 1

        #4
        Hi krungkrung,

        Can you pl tell that where the "JavaScript " function is written?

        If the javascript function is written within UPDATEPANEL then there is a chance that script manager has discarded that function while rendering the page to browser. So I'd suggest to keep the function in separate file and register script file from the code behind.

        Hope it helps,

        Sudev Gandhi

        Comment

        • Frinavale
          Recognized Expert Expert
          • Oct 2006
          • 9749

          #5
          Sudev could be right...

          You may need to register your JavaScript function with the ScriptManager.. .

          We won't know until you share with us the error details that FireBug or IE8 tells you and give us more details on where/how you are defining your JS.

          :)

          -Frinny

          Comment

          • krungkrung
            New Member
            • Nov 2008
            • 18

            #6
            hi Frinny and sudevg!

            thanks for your generous reply.

            sorry i forgot to post quickly, but i already figured out the problem.

            the problem was just the control id being passed to the function. i found out that asp.net(correct me if am wrong) generates control id automatically, of every control within a page upon processing. eg, txtTextInput component would generate something like ctrl001_xxxxx_t xtTextinput control id. So if I pass the "txtTextInp ut", which is the control's name, to the function, the javascript's document.getEle mentById('txtTe xtInput') will return nothing since "txtTextInp ut" is not considered or identified as a control id of any control found within the page.

            so here's what i did..though i think its kinda ugly but its the simplest way i could think for the mean time(if you have any idea i would be more than grateful if you share it to me)...from the code behind I pass the control's client Id to java script function...like , "txtTextinput.C lientID"...and that's it. as simple as that and my whole day was even brighter when I made it run after a couple of hours thinking what should be the problem of the program when I know I coded it correctly....ch eers!

            Comment

            • Frinavale
              Recognized Expert Expert
              • Oct 2006
              • 9749

              #7
              The "control id" is accessible in your .NET code using the ClientID property of ASP.NET controls.

              There are a few things that I can add to this.

              First of all, if your element is calling a JavaScript method that does something to that element, you can access that element by referring to "this" in JavaScript.

              For example, the following TextBox calls the JavaScript method "toUpper()" which changes the text entered into upper case. Note how I'm passing "this" as the parameter..."th is" refers to the TextBox element (for simplicity sake I'm using pure HTML instead of asp for this example):
              Code:
              <html>
              <body>
                <script type="text/javascript>
                  function toUpper(element){
                     element.value=element.value.toUpperCase();    
                  }
                </script>
                Enter some text: <input type="text" id="myTextBox" onkeyup="toUpper(this);" />
              </body>
              </html>
              You can do the same thing with ASP elements....jus t pass the JavaScript function "this" and you'll have a reference to the element in your JavaScript.

              If the JavaScript method does not modify the element that is calling it then you'll have to change things around a bit. Sometimes, if you don't want to pass the ClientID of the asp.net control into the method, you can dynamically print the ClientID directly into the JavaScript by calling the Response.Write( ) method using ASP.

              In your ASP page you would have something like this:
              Code:
                Enter some text: <asp:TextBox ID="myTextBox" runat="server" />
              
                <script type="text/javascript>
                  function toUpper(){
                    var element = $get('<%= myTextBox.ClientID %>');
              
                    //The $get method is a method made available to us in the Ajax.NET
                    //framework. The Ajax.NET Framework is included with the page when
                    //you add a ScriptManager to the page. Since you have a ScriptManager
                   //on the page, you have access to this method. It is a short hand for
                   //JavaScript: document.getElementById() method. The following
                   //would accomplish the same thing:
                    //var element = document.getElementById('<%= myTextBox.ClientID %>');
              
                     element.value=element.value.toUpperCase();    
                  }
                </script>
              Where in your .NET code you set the "onkeyup" for the myTextBox element.

              Please note that <%= %> is class asp short hand for calling the Response.Write method. This will write the ClientID directly into the page so that you don't have to pass anything to the method.

              This is only possible if your ASP element is on the same page as the JavaScript that it uses. If it's not on the same page then it's easier to just pass the element to the function.


              -Frinny

              Comment

              • krungkrung
                New Member
                • Nov 2008
                • 18

                #8
                Hi Frinny! Thanks for that very informative post. I really appreciate it. Im kinda..'wow!'.. and realized that I still have a lot of things to learn in asp.net....waaa yyy to go krungkrung..(", )


                thanks..thanks. really.

                Comment

                • krungkrung
                  New Member
                  • Nov 2008
                  • 18

                  #9
                  Hi Frinny!

                  I just have a follow-up question...is it possible to pass a 'Page' as parameter from .Net procedure to a JavaScript function and return that passed 'Page' parameter to a VB.Net function...like :


                  Code:
                  Sub FromNet()
                  Dim strTest As String = "<script language=javascript id='myClientScript'>ToJavaScript(" & MyPage & ");</script>"
                          Page.ClientScript.RegisterStartupScript(Me.GetType(), "testing", strTest )
                  End Sub
                  and the JavaScript would be:
                  Code:
                  function ToJavaScript(objPage)
                  {
                      PageMethods.ReturnToNet(objPage);
                  }

                  Code:
                  Public Shared Sub ReturnToNet(ByVal myPage As Page)
                  
                  call Kachurvahan(myPage )
                  
                  End Sub

                  Comment

                  • Frinavale
                    Recognized Expert Expert
                    • Oct 2006
                    • 9749

                    #10
                    No this isn't possible.
                    The Page Object is a .NET Object....it doesn't exist in the browser.

                    What are you trying to do?

                    Comment

                    • krungkrung
                      New Member
                      • Nov 2008
                      • 18

                      #11
                      Hi Frinny!

                      Thanks for asking.

                      Well, I dont know how am I supposed to tell and explain to you what I really want to do with my program....I just feel its kinda 'awkward' or embarrassing posting or sharing my 'noob' way of coding :) ...but I believe sometimes people need to be criticized to learn from others opinion...so I'll just try my best to explain it to you.

                      Here's what I want to do:

                      (Presentation:)
                      1. A page that has a maximum of 8 thumbnail images loaded in it.
                      2. An image container(bigge r than the thumbnail images) for displaying of selected thumbnail image
                      3. A left and right navigations(so I can navigate images more than the maximum, eg. 9 - 30).
                      4. A delete button(deletes a selected image)

                      (Events:)
                      1. Upon loading of the page the default selected image would be the first thumbnail
                      2. Clicking thumbnail pic will display the image to image container..WITH OUT POSTING BACK.
                      3. Clicking the LR navigation buttons will navigate through other pics not currently displayed..WITH OUT POSTING BACK
                      4. Hitting delete button will delete the pic from the directory and database and refreshes the page(calling the function called in Page_Load)..WIT HOUT POSTING BACK.


                      Here's what I did:

                      1. Created a function(LoadAl lPhotos) that saved the images in an array using ClientScript.Re gisterArrayDecl aration. So basically, images are preloaded.

                      2. Placed LoadAllPhotos in 'Page_Load' event

                      3. Upon calling the LoadAllPhotos(o r inside my LoadAllPhotos). .I call the LoadPicture() and NavigatePicsRig ht() JavaScript functions using ClientScript.Re gisterStartupSc ript

                      ***LoadPicture( ) -- is a function called when thumbnail is clicked
                      ***NavigatePics Right() -- is a function called when the R nav btn is clicked and displays other preloaded thumbnail images within a page.

                      4. Hitting delete btn should delete Image and calls back the LoadAllPhotos() function(to refresh array of preloaded images) without posting back. -->unfortunatel y I still unable to do this using PageMethods since I placed the function LoadPicture() inside the current page which supposed to be in a PageBase.


                      Here's my code:


                      Code:
                      
                          Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
                      
                              If Page.IsPostBack = False Then
                                  Call LoadAllPhotos(Request.QueryString("traceid"))
                              End If
                          End Sub
                      
                      Protected Sub LoadAllPhotos(ByVal intUserTraceId As Integer)
                              Dim _clsColPicture As New List(Of Picture)
                              Dim _clsPictureBL As New PictureBL
                              Dim _clsDBTransaction As New DBTransaction
                              Dim _shrtPicCount As Short
                              Dim _strHTM As String = ""
                              Dim _strImgBorder = ""
                      
                              Dim strFilePath As String = "images/" & Left("0000000000", 10 - Len(intUserTraceId.ToString)) & intUserTraceId & "/Images/"
                              Dim strFileName As String = ""
                      
                              Try
                                  _clsDBTransaction.BeginTransaction()
                                  _clsPictureBL.RetrievePics(_clsColPicture, intUserTraceId)
                                  For _shrtPicCount = 0 To _clsColPicture.Count - 1
                                      strFileName = strFilePath & "t_" & _clsColPicture(_shrtPicCount).FileName.ToString
                      
                                      Me.ClientScript.RegisterArrayDeclaration("arrPhotos", "'" & strFileName.Trim.ToString & "'")
                                      Me.ClientScript.RegisterArrayDeclaration("arrPicOwner", _clsColPicture(_shrtPicCount).OwnerId)
                                      Me.ClientScript.RegisterArrayDeclaration("arrPicIndex", _clsColPicture(_shrtPicCount).Id)
                      
                      
                                      If _shrtPicCount <= 0 Then
                                          'load first image if any
                                          Dim strFirtsImg As String = "<script language=javascript id='myClientScript'>LoadPicture('" & strFileName.ToString & "', " & _clsColPicture(_shrtPicCount).OwnerId & ", " & _clsColPicture(_shrtPicCount).Id & ", " & Request.Cookies("TraceIdCookie").Value & ");</script>"
                                          Page.ClientScript.RegisterStartupScript(Me.GetType(), "callLoadFirstPic", strFirtsImg)
                                      End If
                                  Next
                      
                                  'call javascript function NavigatePicsRight to load first group of pics
                                  Dim strScript As String = "<script language=javascript id='myClientScript'>NavigatePicsRight();</script>"
                                  Page.ClientScript.RegisterStartupScript(Me.GetType(), "callNavigatePicsRight", strScript)
                      
                                  _clsDBTransaction.CommitTransaction()
                              Catch ex As Exception
                                  _clsDBTransaction.RollbackTransaction()
                              Finally
                                  _clsDBTransaction.EndTransaction()
                              End Try
                          End Sub
                      Here's my JavaScript function
                      Code:
                      //function for navigation of loaded pics
                      function NavigatePicsRight()
                      {
                          var strHtml = "";
                          var index; 
                      
                          ClearWarningText();
                      
                          if(i>arrPhotos.length-1) {
                             return;
                          }
                          
                          var strCookie = "";
                          strCookie = getCookie("TraceIdCookie");
                          
                          ii++;
                          iii = 0;
                          strHtml = "<table><tr>";
                          for(index=0;index < 8;index++)
                          {	            
                              if(i<=arrPhotos.length-1) {		         
                                  strHtml = strHtml + '<td><img src="'+arrPhotos[i]+'" Height="40px" Width="59px" onclick="javascript:LoadPicture(''+arrPhotos[i]+'', '+arrPicOwner[i]+', '+arrPicIndex[i]+', '+strCookie+');" onmouseover="this.style.cursor='hand';"/></td>';   
                                  i++;
                                  iii++;
                              }          	            
                          }	        
                          strHtml = strHtml + "</tr></table>"
                          document.getElementById("div_photoframe").innerHTML = strHtml;
                      } 
                      
                      function LoadPicture(strPicture, intPicOwner, intPicIndex, intCurrentUserId)
                      {
                         var strNewString = "";
                         var strToFind = "";   
                         var expires = "";
                         
                         ClearWarningText();
                         
                         strToFind = strPicture.substring(strPicture.lastIndexOf("t_"));
                         strNewString = strPicture.substring(strPicture.lastIndexOf("t_") + 2);
                         
                         document.cookie = "PictureIndexCookie="+intPicIndex+"; "+expires+"; path=/";   
                         document.cookie = "PictureFileNameCookie="+strNewString+"; "+expires+"; path=/";   
                         
                         document.getElementById("picholder").innerHTML = '<img src="'+strPicture.replace(strToFind, strNewString)+'"  />';
                      
                      
                      }



                      Im just thinking if I could place my LoadAllPhotos() procedure inside a base class instead of placing it within the current page


                      Sorry for the lengthy post but I hope I stated my point clearly. Thanks a lot.

                      Comment

                      • krungkrung
                        New Member
                        • Nov 2008
                        • 18

                        #12
                        ERRATUM:

                        4. Hitting delete btn should delete Image and calls back the LoadAllPhotos() function(to refresh array of preloaded images) without posting back. -->unfortunatel y I still unable to do this using PageMethods since I placed the function LoadAllPhotos() inside the current page which supposed to be in a PageBase.

                        Comment

                        • Frinavale
                          Recognized Expert Expert
                          • Oct 2006
                          • 9749

                          #13
                          Originally posted by krungkrung
                          ERRATUM:

                          4. Hitting delete btn should delete Image and calls back the LoadAllPhotos() function(to refresh array of preloaded images) without posting back. -->unfortunatel y I still unable to do this using PageMethods since I placed the function LoadAllPhotos() inside the current page which supposed to be in a PageBase.
                          The .NET code you posted....is it in a content aspx page or is it in the MasterPage?

                          It doesn't really matter which it's in...unless you want the photos to be on every page in your site as opposed to one page.

                          Anyways, your Delete functionality is going to have to postback to the server if you want to delete the image off of the server.

                          It doesn't have to be a full page postback, you can do an asynchronous postback using AJAX.

                          Have you used AJAX before?

                          Comment

                          • krungkrung
                            New Member
                            • Nov 2008
                            • 18

                            #14
                            Hi Frinny! Thanks again.

                            The .NET code I posted resides in the .aspx page and not in the master page. But I want to place it in a Base class. That's why I ask you if a 'Page' object can be used as parameter in .Net to JavaScript function transition, so I can replace the 'Me' with the passed 'Page' object parameter.

                            Nope. Never used AJAX before, but am applying it to my current project. So technically, Im a noob. :).

                            Well, I really don't have much idea on asynchronous postback using AJAX except that it uses Update Panel based from what I read. :D. Can you give me an idea how can I do that? You don't have to give me the code..just a step or a piece of hint on how I can apply that technique to my page...and the rest will be up to me to research. *winks*...thank s a lot Frinny.

                            Comment

                            • Frinavale
                              Recognized Expert Expert
                              • Oct 2006
                              • 9749

                              #15
                              The UpdatePanel makes life easy for you. You place one on the page, and then you place any content that needs to be asynchronously updated within the the UpdatePanel. Now every time any element within the panel postsback to the server only that section of the page is updated upon return.

                              The thing you have to remember is that when you use an UpdatePanel the full ASP Page Cycle occurs on the server.

                              If you don't like this idea, and you just want to call a particular method on the server to do the delete...then consider using pure Ajax. Or you can consider using AJAX with WebServices (I have recently become very fond of this)...but it requires some knowledge of AJAX/JavaScript, JSON, and of course Web Services.

                              One other thing to consider, when registering Dynamic JavaScript in an Ajax enabled website, you should not use the ClientScriptMan ager to do so. Instead you should be registering your JavaScript using the ScriptManager (or ScriptManagerPr oxy).

                              I don't understand what you mean by "Base Class"?
                              I also don't understand what you mean by "JavaScript function transition"...

                              Comment

                              Working...