Personal C Sharp                                                         By  famsoft.org
HomeHow To StartExamples-DesktopExamples-WebPC# MethodsReference-DesktopReference-Web


DEMONSTRATIVE EXAMPLES ====================== WEB PAGE DEVELOPMENT IV ======================= THE MASTER PAGE FILE: ===================== We'll copy WPDIII's master file unchanged. So, after creating the new application folder WPDIV and registering it at the Internet Information Services, copy the file "master1.cs" from WPDIII to WPDIV folder. Next step is to compile the file by executing the command 'pcwm master1' from command mode. ========================================================================================= Animation by moving objects: ============================ The last example in WPDIII showed how to do animation using symbols from the two fonts "Webdings" and "Wingdings". There is one difficulty with those two fonts, which is that not all computer users have them installed into their computers. You can easily solve this problem by sending them dynamic images for the necessary symbols from your server. This should be easy to do and we'll do it later, but we need to solve a problem first which is how to move an image. The Webdings and Wingdings have been characters, so we have been easily moving them by adding leading or trailing spaces to them, then displaying the resulting string at the same location all the time. This is not what we can do to an image. The image control and all other controls which we create in method setup() are installed into table cells. We have no easy way to move them. Now how about the controls which we install using the html loading operation when we load the label of a control (cis) with html code? Before we get into this subject further, we need to finish with an older one. We have seen how to write words, lines and paragraphs using the html loading method. We have also seen how to create tables and hypertexts and how to display the contents of files and web pages using the same method. The only two features which have not been explained yet are creating labels and iamges. If you like to review this subject, see WPDII examples 7:9. We can create a label or an image using absolute positioning which allows us to move them anywhere accross the page. This should be interesting since we can move them far beyond the borders of their containers. Creating a Label Control: ------------------------- You can create a label control, frame it if you like, assign it any foreground and background colors and any font. Additionally, you can make its background transparent. Here are all the parameters: cs : Keyname. Any name to identify the control with. PC# naming rules don't apply here. os : Label's text. cls : foreground-background combined color code. If you like to make the background transparent, you must Use 6-char code like: (cls="r09y00";) meaning fully opaque red foreground and transparent background. fns : Font code. i,o : Width, Height in pixels. ib : Positioning flag. ib=true means requesting absolute positioning. jd : Border width in pixels (if you like to install frame around it.) Creating an image Control: -------------------------- You can also create an image control, frame it if you like, scale it to any size and set its postioning propperty to absolute so you can easily move it accross the page. Here are all the parameters: cs : Keyname. Any name to identify the control with. PC# naming rules don't apply here. ims : URL of the image. os : Alternative text (optional) i,o : desired width and height in pixels. Default: Display image at its actual size. j,k : Empty space to leave around image horizontally and vertically in pixels. ds : Direction. Can be any of (n/s/e/w/c). Sets how text around is aligned relative to image. ib : Positioning flag. ib=true means requesting absolute positioning. jd : Border width in pixels. The default of (jd=0) means not framed. ========================================================================================= Example 1: In this example, we are going to create a transparent label control and an image. The two objects will be moving accross the page. We'll run the page of example 10, WPDIII in the background in order to study how the new objects will interfere with the old ones. Most of the code is for generating the old page. Only the new additives will be marked and commented. ========================================================================================= public partial class pg1:master1 { public override void init() { base.init(); } public override void setup() { base.setup(); //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 2 cols, 2 rows cs="lb0";cis="|";j=0;k=0;ds="c"; fns="wn48";cls="r0p7";wm("i"); cs="lb1";cis="|";j=1;k=0;ds="c"; fns="wn48";cls="b0p7";wm("i"); cs="lb2";cis="?";j=0;k=1;i=2;of=50;ds="sw"; fns="wn48";cls="S9p7";wm("i"); //----------------------------------- tb3 Contents ---------------------------------- cns="tb3"; // tb3 is made of 2 cols, 3 rows cs="lb3";cis="j";j=0;k=0;i=2;ds="nw";cls="S9p7";fns="wb42";wm("i"); cs="lb4";cis="Progress Bar";j=0;k=1;ds="c";lf=80;cls="r0p7";fns="trb12";wm("i"); cs="lb5";cis="g";j=1;k=1;ds="w";lf=160;of=19;cls="b0y0";fns="wb10";os="w";wm("i"); //********************************* New additive ********************************** cs="lb6";j=0;k=2;wm("i"); // Two label controls are used to cs="lb7";j=1;k=2;wm("i"); // create the new objects into. } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; setup(); MakePage(table); PageNumber(1); //********************************* New additive ********************************** // REMARK: You need to replace the square brackets around "br" with angled ones. wm("o"); // Open a new html loading operation. cs="myLabel";os="[br] Famsoft";ib=true; // Create new label control using the keyname // "myLabel", os=label text,use absolute pos. i=85;o=120;cls="r09y00";fns="es22";jd=5; // Label size, color, font and border width wm("db"); // Notice that background is transparent. wm("c");cs="lb6";wm("sl"); // Close loading operation and set the (cis) wm("o"); // Open a new html loading operation. cs="myImage";ims="../images/flower.jpg"; // Create new image control using the keyname ib=true;i=85;o=100;jd=5;wm("di"); // "myImage",absolute pos,scaled to 85X100. wm("c");cs="lb7";wm("sl"); // Close loading operation and set the (cis) //************************************************************************************ // Variable used: s=int value which determines how each item is displayed. Can be 0:9 // Define new variable to use in next operation: s= symbol order in each group (0:9) cs=ks=""; os="var s=0;"; wm("js"); cs=ks="pl"; i=500; os="s++;if(s>9) s=0;"; //--------------------------------- Red Rose ---------------------------------------- os+="fns='wn'+15*s;"; os+="cs='lb0';cm('sf');"; os+="cis='|';cs='lb0';cm('sl');"; //--------------------------------- Blue Rose --------------------------------------- os+="fns='wn'+15*s;"; os+="cs='lb1';cm('sf');"; os+="cis='|';cs='lb1';cm('sl');"; //-------------------------------- Writing Hand ------------------------------------- os+="cm('o');"; os+="cls='b0';fns='trb12';"; os+="j=10;os='Great animation by Personal C Sharp. '.substr(0,s*4);cm('h');"; os+="cls='S9';fns='wn48';"; os+="os='?';cm('h');cm('c');"; os+="cs='lb2';cm('sl');"; //----------------------------------- Plane ----------------------------------------- os+="cm('o');"; os+="j=10-s;os='j ';cm('h');"; os+="cm('c');"; os+="cs='lb3';cm('sl');"; //-------------------------------- Progress Bar ------------------------------------- os+="cis='';"; os+="for(var i=0;i< s+1;i++) cis+='g';"; os+="cs='lb5';cm('sl');"; //********************************** New additive *********************************** os+="cs='myLabel';j=70*s-348;k=100;cm('sB');"; //$ Set horiz position as a function //$ of (s) and vert pos as a constant os+="cs='myImage';j=70*s-352;k=-100;cm('sB');"; //$ Do same for the Image control. //*********************************************************************************** wm("js"); // Send the script block } } ========================================================================================= COMMENTS: --------- (1) In order to create the new two controls we needed to create two ASP.NET label controls. We set them at the bottom of other controls. However, their locations and their sizes are irrelevant. Since we are using absolute positioning, we are able to move the new controls anywhere within the page regardless to the sizes or locations of their containers. (2) When we have been moving character symbols, we have been adding spaces to them then using them to modify the ASP.NET control labels. Here, we have created a new independant controls at the C# section of the code. At the JavaScript section, we have no need to modify the original controls. We only need to modify the "bounds" property of the new controls in order to make them move. (3) The absolute positioning parameters (j,k) for the label and the image are made relative to the center. This will be discussed in details when we get to example 9.


========================================================================================= Converting Webdings and Wingdings symbols into images: ====================================================== There are 446 different drawings included into the two fonts. This is why this operation is valuable. We need to make a general method which can be called to convert any symbol into an image and send it to the requesting web page dynamically. Making a general character to image converter method: ----------------------------------------------------- When we have been working with the symbols as characters, our job has been simpler. We have been able to change their colors on the fly, additionally characters have no background naturally which helps animation. Now, we must supply the method with our chosen color for each symbol and also with our wanted background color which should match the page's color. Also, we need to supply the method with the font code and the character wanted. There are symbols for all the range of (33:255) ASCII codes. So we must use ASCII codes to identify them. In conclusion we need to supply the method with: (1) Foreground-Background color code. (2) Font code. (3) ASCII code for the symbol. The 3 parameters will be attached to the page's aspx file as a query string making the image URL for the dynamically generated image. When the page starts, it will extract the 3 parameters and call the method. The symbols are of different sizes and we like the image generated to be slightly larger than the symbol in order to show it well, but not any larger. So, the method makes the image 10% larger than the bounding rectangle of the symbol. The last problem we have met was that symbols are not evenly aligned vertically within their character boundary. So the method measures the vertical displacement of each symbol and compensates for it when the symbol is finally drawn to generate the image. Making a demonstration program: ------------------------------- Before we use the symbols in their graphical form, we need to test the method we have created manually. We need to write a program which gets the 3 parameters from the user and supply the method with them then displays the resulting image. When the method is used practically, the parameters come as a query string. We are going to maintain this, except that this program will check for the user supplied parameters. If it finds them available, it'll overwrite the query data with them. public partial class pg2:master1 { string color="",font="",code=""; // Defining new variables public override void init() { base.init(); } public override void setup() { base.setup(); // Run setup() of master page first //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 2 cols, 5 rows cs="lb0";cis="Get A Symbol IN Graphical Form"; // Label control for Title j=0;k=0;i=2;ds="c";cls="s9G1";fns="trb14";wm("i"); wm("o");ds="w";cls="b0";fns="trbi12"; os="Get a symbol from Webdings or Wingdings font list. Color code should be a valid"; os+=" PC# 4-char code for the foreground and background like 'b0p7'. Normally, you "; os+="like the background part to match page's color which is 'p7'. Font code should"; os+=" be a valid PC# code like 'wb200' or 'wn40'. ASCII code is any number between "; os+="33 and 255.";wm("dp"); wm("c"); cs="lt0";j=0;k=1;o=4;wm("i"); // Literal control for Description cs="tf0";cis="Color code";j=1;k=1;jf=10;ds="c";cls="b0o5";fns="trb12";wm("i"); cs="tf1";cis="Font Code";j=1;k=2;i=1;jf=10;ds="c";cls="b0o5";fns="trb12";wm("i"); cs="tf2";cis="ASCII Code";j=1;k=3;i=1;jf=10;ds="c";cls="b0o5";fns="trb12";wm("i"); cs="bt0";cis="Get Symbol";j=1;k=4;ds="c";cls="r0g8";fns="trb12";wm("i"); //----------------------------------- tb3 Contents ------------------------------------ cns="tb3"; // tb3 is made of 1 col, 1 row1 cs="im2";j=0;k=0;o=1;ds="c";ims="pg2.aspx?color=S9p7&font=wb200&code=255";wm("i"); } //------------------------------------------------------------------------------------- public override void update() { if (cs.Equals("pl")) { // If Page_Load event: //----------------------------- If here for the image -------------------------- ks="color";wm("rq");color=OS[0]; // Get the value of the par "color" ks="font";wm("rq");font=OS[0]; // Get the value of the par "font" ks="code";wm("rq");code=OS[0]; // Get the value of the par "code" if (code.Length>0) { // If query string available: ks="color_s";wm("vg");if (os.Length>0) color=os; ks="font_s";wm("vg");if (os.Length>0) font=os; ks="code_s";wm("vg");if (os.Length>0) code=os; // Check user supplied par's. Ovewrite // query par's with them if available GetSymbol();return; // Run method and return. } //----------------------------- If here for the page ---------------------------- wm("ir"); // Else: Clear installation variables setup(); MakePage(table); PageNumber(2); // Generate the page. } //--------------------------- If Submit button clicked -------------------------- else if (cs.Equals("bt0")) { // If submit button clicked: cs="tf0";wm("gu");color=cus;ks="color_s";os=cus;wm("vs"); cs="tf1";wm("gu");font=cus;ks="font_s";os=cus;wm("vs"); cs="tf2";wm("gu");code=cus;ks="code_s";os=cus;wm("vs"); // Save user data and return. } } //------------------------------ Generating the symbol ------------------------------ void GetSymbol() { // var's used: color,font,code=Suppied data fs,bs=Foreground, background color codes // wf,hf=Width and height of symbol's bounding rectangle. // yf: Vertical displacement of symbol's center relative to character // boundaries' center. lf=of=200;wm("bo"); // Open new bitmap operation using // bio of size 200 X 200 pixels. if(color.Length!=4 && color.Length!=6) color="S9p7"; // If color code invalid, use default if(color.Length==4) { // If 4-char color code, seperate fs=color.Substring(0,2);bs=color.Substring(2);// foreground and background codes } else { // Do the same if 6-char code fs=color.Substring(0,3);bs=color.Substring(3); } if (font.Length<3) fns="wb100"; // If font code invalid, use default os=code;om("ti");c=o; // Convert code to integer if (c<33 ||c>255) c=255; // If beyond range, use default fns=font;os=""+(char)o;gm("ct"); // Create (gpp) for the symbol gm("gw");om("tf");float wf=of; // Get (gpp)'s width, assign to (wf) gm("gh");om("tf");float hf=of; // Get (gpp)'s height, assign to (hf) gm("gy");om("tf");float yf=of; // Get (gpp)'s vert displacement in (yf) lf=1.1f*wf;of=1.1f*hf;gm("bn"); // Create (bip) of 10% larger size gm("sdb"); // Make (bip) the graphical out device cls=bs;gm("ec"); // Paint background with requested color cls=fs;gm("sps"); // Prepare brush with req foregrnd color jf=0;kf=-yf;os=""+(char)c;gm("ctf"); // Create symbol again compensating for // vert displacement, fill with paint bio=bip; // Make (bio) refer to (bip)'s object wm("bc"); // Close bitmap operation } }


========================================================================================== Using the symbols in their image form: ====================================== If we like to duplicate the last example of WPDIII using the image form of the symbols, we must find means to do 3 operations to an image: Positioning, Scaling and Concatenating. Positioning was necessary for the flying plane and the writing hand. Scaling was necessary for the growing flower. Concatenating was necessary for the progress bar. We can easily move an image by assigning the new location's (x,y) to (j,k) and calling cm("sB"); which means "Set Bounds". We can scale an image by assigning the new width and height to (i,o) and calling the same method cm("sB") We can actually do both operations more smoothly with images since changes can be as small as one pixel at a time which has not been possible with characters. Concatenation cannot be done easily with images, so we must find another way. A simple way is to scale the square block horizontally with a growing amount so it turns into a line which is growing in length. This is exactly what is required to make a progress bar. ========================================================================================== Example 3: This example shows how a combination of scaling and movement can make a race car appear to be cutting a long distance while travelling accross the monitor's screen. Additionally it shows how to duplicate the progress bar using the image of a square block. ========================================================================================== public partial class pg3:master1 { string color="",font="",code=""; // Defining new variables public override void init() { IsSingleTable=true; // Request Single Table Page. base.init(); } public override void setup() { base.setup(); // Run setup() of master page first //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 1 col, 3 rows cs="lb0";j=0;k=0;ds="se";wm("i"); // Car image will be created here cs="lb1";j=0;k=1;ds="s";lf=160;of=19;cls="b0y0";wm("i"); // Bar's outer yellow strip cs="lb2";j=0;k=2;wm("i"); // Bar image will be created here } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; // If not Page_Load event, return. //----------------------------- If here for the image -------------------------- ks="color";wm("rq");color=OS[0]; // Get the value of the par "color" ks="font";wm("rq");font=OS[0]; // Get the value of the par "font" ks="code";wm("rq");code=OS[0]; // Get the value of the par "code" if(code.Length>0) {GetSymbol();return;} // If query available. run method, return //----------------------------- If here for the page ---------------------------- wm("ir"); // Else: Clear installation variables setup(); MakePage(table); PageNumber(3); // Generate the page. cs="tb2";lf=760;of=300;wm("sB"); // Reduce page's height. //-------------------------- Create Car's Image Control -------------------------- wm("o"); // Open a new html loading operation. cs="car";ims="pg3.aspx?color=S9p7&font=wb100&code=141"; ib=true;wm("di"); // use absolute positioning, make control wm("c");cs="lb0";wm("sl"); // Close loading operation and set (cis) //-------------------------- Create Bar's Image Control -------------------------- wm("o"); // Open a new html loading operation. cs="bar";ims="pg3.aspx?color=b0y0&font=wb10&code=103"; ib=true;wm("di"); // use absolute positioning, make control wm("c");cs="lb2";wm("sl"); // Close loading operation and set (cis) //-------------------------------- Animation loop -------------------------------- cs=ks=""; // At start do: os="var s=0;"; //$ Define global var (s) wm("js"); // Send the script block cs=ks="pl"; // When page loaded & onload ev on do: i=1; // Repeat execution with 1 ms delay os="s++;if(s>99) s=0;"; //$ Set (s) value for next operation //$ Loop back when 100 is reached. os+="cs='car';j=-360+7*s;k=0;"; //$ Set car's new position os+="i=10+s*2;cm('sB');"; //$ and new size. os+="cs='bar';j=s*3/4-70;k=-195;"; //$ Set bar's new position os+="i=(s*3/2);o=12;cm('sB');"; //$ and new size. //$ and height at 12 pixels constantly. wm("js"); // Send the script block } //------------------------- Generating the symbol (No change) ------------------------- void GetSymbol() { // var's used: color,font,code=Suppied data fs,bs=Foreground, background color codes // wf,hf=Width and height of symbol's bounding rectangle. // yf: Vertical displacement of symbol's center relative to character // boundaries' center. lf=of=200;wm("bo"); // Open new bitmap operation using // bio of size 200 X 200 pixels. if(color.Length!=4 && color.Length!=6) color="S9p7"; // If color code invalid, use default if(color.Length==4) { // If 4-char color code, seperate fs=color.Substring(0,2);bs=color.Substring(2);// foreground and background codes } else { // Do the same if 6-char code fs=color.Substring(0,3);bs=color.Substring(3); } if (font.Length<3) fns="wb100"; // If font code invalid, use default os=code;om("ti");c=o; // Convert code to integer if (c<33 ||c>255) c=255; // If beyond range, use default fns=font;os=""+(char)o;gm("ct"); // Create (gpp) for the symbol gm("gw");om("tf");float wf=of; // Get (gpp)'s width, assign to (wf) gm("gh");om("tf");float hf=of; // Get (gpp)'s height, assign to (hf) gm("gy");om("tf");float yf=of; // Get (gpp)'s vert displacement in (yf) lf=1.1f*wf;of=1.1f*hf;gm("bn"); // Create (bip) of 10% larger size gm("sdb"); // Make (bip) the graphical out device cls=bs;gm("ec"); // Paint background with requested color cls=fs;gm("sps"); // Prepare brush with req foregrnd color jf=0;kf=-yf;os=""+(char)c;gm("ctf"); // Create symbol again compensating for // vert displacement, fill with paint bio=bip; // Make (bio) refer to (bip)'s object wm("bc"); // Close bitmap operation } } ========================================================================================== Notice that when we set the size of the car, we specify width only. This way, the height is computed automatically maintaining width/height proportionality. Notice also that (j,k) are measured relative to the center. This will be discussed in details when we get to example 9. I know some of you have noticed that the car smashes the right wall as it drives. We are not worried since this is not too unusual for a race car! LIMITING THE NUMBER OF REPITITIONS: =================================== It is nice to watch that race car, but don't do it for too long. In real life, you can't keep something which runs endlessly into a web page and expect the viewers to be happy. Therefore you must stop the animation after a tolerable number of repititions. If you return back to the title "How to write JavaScript statements" there has been 5 parameters to be set. We have used all of them in the past examples except the last one which is (j). If you assign a number to (j) other than zero, The animation will stop after the number of repititions reaches that number. To test this parameter add the statement (j=99;) immediately following the line (i=1;) and run the page. You should notice that the car moves until it reachs the right side margin then stops. If you change it to (j=199;), it will make two trips then stop at the same location. FOR JAVASCRIPT EXPERTS ONLY: ---------------------------- At the start of the JavaScript topic we have mentioned that we have made sure that the help PC# offer for JavaScript does not prevent the ones who prefer to do their JavaScript programming on their own from doing so. In order to make sure this is understood properly, we are going to repeat this example with eliminating PC#'s help. Please look at the rules under the title "WHAT DO WE HAVA FOR THE JAVASCRIPT EXPERTS?" again before getting further. For the ones who are satisfied with our help, you can skip this section. You start by adding (jsi=0;) to method init(). Now you should know that PC# file will not be sent, so calling method cm("sB") is meaningless. The GUV's are not defined either. So we need to do all that on our own. The best to do is to create our own script file which contains a function named setBounds() and define all the variables required for the function. Here is how the file contents will be: var i,j,k,o,cs; //$ Define necessary var's function setBounds() { //$ Function definition var cnp=document.getElementById(cs); //$ Get a reference to the object specified if (i>0) cnp.style.width=i; //$ Set Width=i if (o>0) cnp.style.height=o; //$ Set Height=o if (j>0) cnp.style.posLeft=cnp.style.left=j; //$ Set start position from left=j if (k>0) cnp.style.posTop=cnp.style.top=k; //$ Set start position from top=k i=o=j=k=0;cs=""; //$ Reset var's } Notice that we used 2 ways when setting position, one works with the Internrt Explorer and the other works with other browsers. Make the file using NotePad and save it under the name "myScript.js" into the application folder. Now modify the page class as follows: ======================================================================================== public partial class pg3:master1 { string color="",font="",code=""; public override void init() { IsSingleTable=true; jsi=0; // **** new: JS level=0 base.init(); } //====================================== No change ==================================== public override void setup() { base.setup(); cns="tb2"; cs="lb0";j=0;k=0;wm("i"); cs="lb1";j=0;k=1;ds="s";lf=160;of=19;cls="b0y0";wm("i"); cs="lb2";j=0;k=2;wm("i"); } public override void update() { if (!cs.Equals("pl")) return; ks="color";wm("rq");color=OS[0]; ks="font";wm("rq");font=OS[0]; ks="code";wm("rq");code=OS[0]; if(code.Length>0) {GetSymbol();return;} wm("ir"); setup(); MakePage(table); PageNumber(3); cs="tb2";lf=760;of=300;wm("sB"); //====================================================================================== fls="myScript.js";wm("jf"); // **** new: Send Script File //====================================== NO CHANGE ===================================== wm("o"); cs="car";ims="pg3.aspx?color=S9p7&font=wb100&code=141"; ib=true;wm("di"); wm("c");cs="lb0";wm("sl"); wm("o"); cs="bar";ims="pg3.aspx?color=b0y0&font=wb10&code=103"; ib=true;wm("di"); wm("c");cs="lb2";wm("sl"); //******************************* ANIMATION LOOP: MODIFIED ****************************** cs=ks=""; // At start do: os="var s=0,delay=1,repititions=199;"; //$ Define global var's (s,delay,repititions) wm("js"); // Send the script block cs=ks="pl"; // When page loaded & onload ev on do: os ="function move() {"; //$ Define a new function: os+=" s++;if(s>99) s=0;"; //$ Set (s) value for next operation //$ Loop back after 100 repititions os+=" cs='car';j=20+6*s;k=200;"; //$ Set car's new postion os+=" i=10+s*2;setBounds();"; //$ and new size. os+=" cs='bar';j=320;k=406;"; //$ Set bar's new position os+=" i=(s*3/2);o=12;setBounds();"; //$ and new size. os+=" repititions--;"; //$ Decrement repititions os+=" if (repititions>0) window.setTimeout('move();',delay);"; os+="}"; //$ function calls itself after delay wm("js"); // Send the script block } //=========================== GENERATING THE SYMBOL: NO CHANGE ======================== void GetSymbol() { lf=of=200;wm("bo"); if(color.Length!=4 && color.Length!=6) color="S9p7"; if(color.Length==4) { fs=color.Substring(0,2);bs=color.Substring(2); } else { fs=color.Substring(0,3);bs=color.Substring(3); } if (font.Length<3) fns="wb100"; os=code;om("ti");c=o; if (c<33 ||c>255) c=255; fns=font;os=""+(char)o;gm("ct"); gm("gw");om("tf");float wf=of; gm("gh");om("tf");float hf=of; gm("gy");om("tf");float yf=of; lf=1.1f*wf;of=1.1f*hf;gm("bn"); gm("sdb"); cls=bs;gm("ec"); cls=fs;gm("sps"); jf=0;kf=-yf;os=""+(char)c;gm("ctf"); bio=bip; wm("bc"); } } ======================================================================================== If you run this page, the car should make two trips then stop.


========================================================================================== ANIMATION BY COLOR CHANGE: ========================== The JavaScript function um() at mode "x" can mix two PC# color codes at any ratios you like. The resulting color code comes in the hex format which is necessary for general html use. You combine the two codes into one like "r0b0" and assign them to (cls) before supplying them to the function. You also supply the percentage amount of the first color in the mix assigned to (i). The resulting code can be used to set the foreground or background color of any control using function cm() at modes "sc" and "scb" respectively. Mixing colors can be used for animation. For example, you can make an object appear to be fading until it completely disappears when you change its color gradually to the page's color. ========================================================================================== Example 5: This example shows different types of animations by changing color. ========================================================================================== public partial class pg4:master1 { public override void init() { base.init(); } public override void setup() { base.setup(); //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 2 cols, 2 rows cs="lb0";cis="|";j=0;k=0;ds="c"; fns="wn148";cls="r0p7";wm("i"); cs="lb1";cis="|";j=1;k=0;ds="c"; fns="wn148";cls="b0p7";wm("i"); cs="lb2";cis="FADING TEXT";j=0;k=1;i=2;of=50;ds="sw"; fns="trb20";cls="S9p7";wm("i"); //----------------------------------- tb3 Contents ---------------------------------- cns="tb3"; // tb3 is made of 1 col, 2 rows // Replace the square brackets around [br] with angled ones. cs="lb3";cis="[br]FADING SIGN";j=0;k=0;lf=300;of=100;ds="c";cls="p7p0";fns="trb20";wm("i"); cs="lb5";cis="APPEARING TEXT";j=0;k=1;of=50;ds="sw"; fns="trb20";cls="b0p7";wm("i"); } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; setup(); MakePage(table); PageNumber(4); // Variable used: s=int value which determines how each item is displayed. Can be 0:99 cs=ks=""; // At start: os="var s=0;"; //$ Define new global variable wm("js"); // Send the script block cs=ks="pl"; // When page's onload event is raised i=1; // Repeat each 1 ms os="s++;if(s>99) s=0;"; //$ increment (s), rewind when s=99. //----------------------------- Yellow - Red Rose ----------------------------------- os+="fns='wn'+1.5*s;"; //$ Prepare a growing font in size: os+="cs='lb0';cm('sf');"; //$ Set font os+="cls='r0y0';i=s;um('x');"; //$ Mix colors at a changing percentages os+="cs='lb0';cm('sc');"; //$ Set foreground color os+="cis='|';cs='lb0';cm('sl');"; //$ Display the flower symbol //----------------------------- Green - Blue Rose ----------------------------------- os+="fns='wn'+1.5*s;"; //$ Prepare a growing font in size os+="cs='lb1';cm('sf');"; //$ Set font os+="cls='b0g0';i=s;um('x');"; //$ Mix colors at a changing percentages os+="cs='lb1';cm('sc');"; //$ Set foreground color os+="cis='|';cs='lb1';cm('sl');"; //$ Display the flower symbol //-------------------------------- Fading Text ------------------------------------- os+="cm('o');"; //$ Open a new html loading operation os+="cls='p7S9';i=s;um('x');fns='trb24';"; //$ Mix colors at a changing percentages os+="j=10;os='FADING TEXT';cm('h');cm('c');"; //$ Display text, close loading operation os+="cs='lb2';cm('sl');"; //$ Set (cis) for the control //-------------------------------- Fading Sign ------------------------------------- os+="cls='p7p0';i=s;um('x');"; //$ Mix colors at a changing percentages os+="cs='lb3';cm('scb');"; //$ Set background color //------------------------------- Appearing Text ------------------------------------ os+="cm('o');"; //$ Open a new html loading operation os+="cls='S9p7';i=1*s;um('x');fns='trb24';"; //$ Mix colors at a changing percentages os+="j=4;os='APPEARING TEXT';cm('h');cm('c');"; //$ Display text, close loading operation os+="cs='lb5';cm('sl');"; //$ Set (cis) for the control wm("js"); // Send the script block } }


========================================================================================== COOKIES ======= WHAT IS A COOKIE? ================= A cookie is a file which your browser creates at your computer at the request of a website which you frequently visit. The file contains texetual information which allows them to service you better. After the cookie is made, each time you use your browser to connect you to the same site, the browser sends the cookie with your request to them. COOKIE TYPES: ============= There are two types of cookies: (1) Simple cookie which is merely a" key-value" pair. (2) Complex cookie whose value is made of multiple "key-value" pairs seperated with '&' characters. Cookies can also be categorized in a different manner. They can be: (1) Temporary. This means that they expire when the user closes the browser. (2) Have expiration dates assigned to them. HOW TO SET AND GET COOKIES USING PC#: ===================================== Cookies can be accessed from C# using method wm() or from JavaScript using method cm(). Parameters and modes are identical. Setting expiration date is possible from C# only. Used parameters: ---------------- ks,os : Key & Value of a simple cookie or key & value of one pair of a complex cookie. js : The name of a complex cookie (You may also call it the complex cookie's key). If you keep the default of (js=""), you will be refering to a simple cookie. jb : Expiration date flag. Default (jb=false) means temporary cookie. Otherwise, (jb=true) means use present date object (dtp) as the expiration date. Applicable modes: ----------------- ks : Set cookie. You should supply the wanted key and value assigned to (ks), (os) respectively. If you supply (js=""), you will be setting a simple cookie and if you supply a name to (js), you will be setting one pair in the complex cookie named (js). If a cookie or pair with the same key exists, its value will be overwritten. Otherwise a new "key-value" pair will be created. kg : Get cookie. You supply the key to (ks) and the complex cookie name or "" to (js) The method will return the value of a simple cookie or the value of a pair in a complex cookie which has the same key. ke : Set cookie's expiration date. Make sure that the present date object (dtp) is for the date and time you like the cookie to expire at, then assign the correct value to (js) before calling wm("ke"). The "PC# reference-desktop" explains date and time setup in details. USING COOKIES FOR COMMUNICATION BETWEEN ASP.NET AND JAVASCRIPT: =============================================================== The next example will prove that It is possible to use cookies for such communication. You will see that a cookie which you create in C# can be immediately read by JavaScript and vice versa. So, you can have two ongoing communication channels between them, one for each direction. ========================================================================================= Example 4: Show how to send and receive simple temporary cookies in both C# and JavaScript. Key for all cookies will be "Message" and values will be supplied by user. ========================================================================================= public partial class pg4:master1 { public override void init() { base.init(); } public override void setup() { base.setup(); // Run setup() of master page first //----------------------------------- tb2 Contents ---------------------------------- // C# Section: cns="tb2"; // tb2 is made of 2 cols, 3 rows cs="lb0";cis="COOKIES READING AND WRITING USING C#";j=0;k=0;i=2;ds="c"; cls="r0p7";fns="trb14";wm("i"); // Title cs="ta0";cis="Enter any phrase";j=0;k=1;ds="c";jf=15;kf=3; cls="b0y0";fns="trbi12";wm("i"); // TextArea for creating a cookie cs="ta1";cis="Cookie value:";j=1;k=1;ds="c";jf=15;kf=3; cls="b0y0";fns="trbi12";wm("i"); // TextArea for reading a cookie cs="bt0";cis="Make Cookie";j=0;k=2;ds="c"; cls="r0g8";fns="trb12";wm("i"); // Make Cookie button cs="bt1";cis="Read Cookie";j=1;k=2;ds="c"; cls="r0g8";fns="trb12";wm("i"); // Read Cookie button //----------------------------------- tb3 Contents ---------------------------------- // JavaScript Section: cns="tb3"; // tb3 is made of 2 cols, 3 rows cs="lb1";cis="COOKIES READING AND WRITING USING JAVASCRIPT";j=0;k=0;i=2;ds="c"; cls="r0p7";fns="trb14";wm("i"); // Title cs="ta2";cis="Enter any phrase";j=0;k=1;ds="c";jf=15;kf=3; cls="b0y0";fns="trbi12";wm("i"); // TextArea for creating a cookie cs="ta3";cis="Cookie value:";j=1;k=1;ds="c";jf=15;kf=3; cls="b0y0";fns="trbi12";wm("i"); // TextArea for reading a cookie cs="bt2";cis="Make Cookie";j=0;k=2;ds="c"; cls="r0g8";fns="trb12";wm("i"); // Make Cookie button cs="bt3";cis="Read Cookie";j=1;k=2;ds="c"; cls="r0g8";fns="trb12";wm("i"); // Read Cookie button } //------------------------------------------------------------------------------------ public override void update() { if(cs.Equals("pl")) { // If event is "Page_Load" do: setup(); // Execute setup() MakePage(table); // and Make the page PageNumber(4); // Displayt page number //------------------------------ JavaScript Section ------------------------------ cs="bt2";ks="onClick"; // When (bt2) is clicked: os="cs='ta2';cm('gu');os=cus;"; //$ Get text in (ta2), assign to (os) os+="ks='Message';cm('ks');"; //$ Set simple temporary cookie wm("js"); // Send script block cs="bt3";ks="onClick"; // When (bt3) is clicked: os="ks='Message';cm('kg');"; //$ Read available cookie os+="cs='ta3';cus=os;cm('su');"; //$ Display cookie value in (ta3) wm("js"); // Send script block } //------------------------------------ C# Section ---------------------------------- if(cs.Equals("bt0")) { // When (bt0) is clicked: cs="ta0";wm("gu");os=cus; // Get text in (ta0), assign to (os) ks="Message";wm("ks"); // Set simple temporary cookie } if(cs.Equals("bt1")) { // When (bt1) is clicked: ks="Message";wm("kg"); // Read available cookie cs="ta1";cus=os;wm("su"); // Display cookie value in (ta1) } } } ======================================================================================== You must have noticed that a cookie which you make in JavaScript can be accessed immediately from C# and a cookie which you make in C# can be accessed immediately from JavaScript. This can be of use to you as a means of communication between JavaScript and C#. Of course, this is just theory, nobody needs this method of communication since we have a much better one, which is "AJAX".


========================================================================================== AJAX ====== (Available in versions 1.54 and later) WHAT IS AJAX? ============= It means "Asynchronous JavaScript And XML". Don't pay much of attention to its name. It does not have to do its job asynchronously and it does not have to transmit and receive XML encoded data. AJAX value is in allowing us to send a small piece of data to the server and receive its response while the rest of the page is unaffected. If it was not for AJAX, the only way to communicate with the server would be by submitting the form, sending all its data content to the server then receiving the entire page back. Using AJAX in a Personal C Sharp program: ========================================= It is made very simple. Here is all you do: At client side: --------------- You assign the string you like to send to the server to (os) then call cm('ja') Your string will be sent and the server's response will be returned back to you also assigned to (os). At Server side: --------------- You call wm("jar") to receive the client's string assigned to (os). Then you send your response back to the client by assigning it also to (os) and calling wm("jas"). What else is necessary to know? =============================== (1) In order to maximize the benefits of using AJAX, you need to make sure that when AJAX data is received by the server, nothing in the page is executed other than your code for processing the data and sending the response back. To help you with that, the flag (ajb) is used. This flag is assigned (true) by method wm("jar") whenever the page's request is found to be an AJAX one. You use this flag state as a condition for which part of your code should be executed and which part should not. When the page is first called or whenever the user clicks a submit button and the page is submitted, this flag will be assigned (false), you make sure that the setup data is executed and the entire page is reproduced (including all scripts) in this case. Method wm("jar") is the one which determines the state of this flag. So the page should start by calling this method. (2) After sending the server response using wm("jas"), you must follow this method's call with (Response.End();). This is very important since the server should see nothing to be sent other than the AJAX data. If it finds anything unusual, it sends the entire page instead. Let us have an example before we get into other options with AJAX. Normally, when a user is to be authenticated, she enters her user name and password into a form then clicks a button. At the server, her data is checked against a passwords file or database. If found to be valid, the member's page is sent to her. If found to be invalid, the login page is sent back to her in order to give her a second chance. In the next example we are going to create a JavaScript code which sends the user's password alone to the server using AJAX. The server will check the password and send back a message to let the user know if she is approved or not. The page will be running uninterruptedly at the user's browser all the time while the data exchange is happening. ========================================================================================== Example 5: On the left side, a text field will be installed. The user will type her password into the text field then place the mouse cursor anywhere at the right side. A JavaScript code block will read the data and send it to the server then display the message received back from the server to the user. Additionally, it will change the background color of the right side table to green when approved and to red when rejected. ========================================================================================== public partial class pg5:master1 { public override void init() { base.init(); } public override void setup() { base.setup(); // Run setup() of master page first //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 1 col, 3 rows cs="lb0";cis="CLIENT - SERVER COMMUN. WITH AJAX"; j=0;k=0;ds="c";fns="trb14";cls="r0p7";wm("i"); wm("o");ds="c";cls="b0";fns="trbi12"; os="Type one of the three passwords 'apple', 'orange' or 'banana'. then place your"; os+=" mouse cursor any where at the right section of the page. Your password will be"; os+=" sent alone to the sever via AJAX and you'll know the server's response."; os+=" Nothing else from the page will be transmitted either way.";wm("dp"); wm("c"); cs="lt0";j=0;k=1;wm("i"); cs="tf0";cis="Type Your Password";j=0;k=2;ds="c";jf=20;cls="b0y0";fns="trbi12";wm("i"); //----------------------------------- tb3 Contents ---------------------------------- cns="tb3"; // tb3 is made of 1 col, 1 row cs="lb1";cis="Type your password then place the mouse cursor anywhere here."; j=0;k=0;ds="c";ls="s9o0";fns="trb14";wm("i"); } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; // If not Page_Load event return wm("jar"); // If this was AJAX call, receive data if (ajb) { // If found to be AJAX call: if (os.Equals("orange")) { // If password received was "orange": os="Message from the server: Password approved. Welcome aboard."; } // Prepare approval message else { os="Message from the server: Password rejected. Try again."; } // Else prepare rejection message wm("jas");Response.End(); // Send AJAX response and abort. } else { // If was not an AJAX call: setup(); // Install all controls MakePage(table); // and make the page. PageNumber(5); // Set page number cs="tb3";cls="s9o0";wm("sC"); // Modify right side table color cs="tb3";ks="onMouseOver"; // When mouse is over tb3 do: os="cs='tf0';cm('gu');os=cus;"; //$ Get tf0's text into (os) os+="if(os.length>0) cm('ja');"; //$ call AJAX with (os) if not empty os+="var o1s=os;"; //$ Save received text temporarely os+="cs='lb1';cis=o1s;cm('sl');"; //$ and display it into (lb1) os+="if (o1s.indexOf('approved')>-1) "; //$ If server approved password: os+="{cs='tb3';cls='G2';cm('scb');} "; //$ change tb3's backgrd color to green os+="else {cs='tb3';cls='r0';cm('scb');}"; //$ Else change it to red. wm("js"); // Send script block. cs="tb3";ks="onMouseOut"; // When mouse is outside tb3: os="cs='lb1';cis='Type your password then place the mouse cursor anywhere here.';"; os+="cm('sl');"; //$ Display original message into lb1 os+="cs='tb3';cls='o0';cm('scb');"; //$ Change its backgrd color to original wm("js"); // Send script block. } } }


========================================================================================== AJAX OPTIONS: ============= There are two additional optional parameters which you may assign values to when you call method cm('ja'): jb : If you make the assignment (jb=true) the ajax operation will run asynchronously. This means that your program will not wait for it to finish. Some people see an advantage in this since the user will not be interrupted, but you may disagree with them since most of the time the user should wait. If the user who entered her password into the page of last example was not aware that her password was being processed and it took a long time for the process to finish, what could she have done? Most likely, she could have kept entering her password again and again causing a big mess! When you select asynchronous ajax operation, you still write your code exactly as you do when you select synchronous operation. Method wm("js") takes care of adjusting your code for the different requirements. i : Timeout in milliseconds. If the AJAX process could not end by this time, it will be aborted. If you leave the default of (i=0) unchanged, process will be allowed to take as long as it needs to be completed. ========================================================================================= REMOTE METHOD CALLS =================== As we have mentioned before, Personal C Sharp has been designed to be the easiest and simplest means for accessing the .NET. It was made to be used for personal programming purpose, for C# students who like to start with PC# methods then gradually add their own code as they grow, or by professionals who are starting a new project and like to create a startup version of it fast in order to see if it can be done. With time we have discovered that Personal C Sharp can do much more. The uniformity of variables and methods naming, the pre-defined variables and the limited number of the GUV's (General use variables) which make the parameters for all PC# methods have made the advanced features which normally require complicated procedures very easy to do. You have already seen that object serialization which was required by method xm() has been possible to be done automatically without any operation by your side. You have also seen how easy it is to use threads without the fear of data corruption or dead locking. Remote method calls are another example of how powerful Personal C Sharp can be. It can also be made completely invisible to you. AJAX has given us all the tools necessary to do it and it is done. You can write your code in JavaScript which runs at the client and contains calls to methods of class "pasp". This means that you can use JavaScript to create graphics of the same quality as when you do it using C#. How does it work? ================= Remote calls are handled by two methods, both are named rm(). one at the server (in C#) and the other one at the client (in JavaScript). The first one is inaccessable to your program. It receives commands from the second one and immediately executes them in an invisible manner to your program. Actually the execution is completed and the return values are sent back to the client before method update() is called which means before your program at the server starts. Despite that, you still need to know how it works since you write the JavaScript program which interfaces with it. Operation of method rm() of the server: --------------------------------------- The operation of method mm() which handles thread safe access to all class pcs's methods is very similar to the operation of method rm(). Both methods provide a single enterance to every method in the class. They both expect a "mode" string made by concatenating the first char of the method name with the mode string required to access the method with. For example if you like to call om("ti"), you supply the mode string "oti" to method rm(). Method mm() requires the calling thread number in addition to the mode string but method rm() requires nothing else other than the parameters and the mode string. Method mm() is available in class (pcs) only. Class (pasp) does not contain this method since it does not handle multi-threads. Methods m0():m9(): ------------------ Remote method calls are made to execute one method per call (although there are exceptions to this). This means that if you call method gm() for example to create the shape object for a rectangle. It will create it, but when you make another call to work on the object, it will not find it. The solution is in doing the same as we did with threads. Create a method which includes all necessary statements and call the method to execute them all at once. The method name must be one of the names method rm() is aware of which are m0(),m1(),...., m9() Again methods m0():m9() of class (pasp) which are used for remote calls are not exactly the same as the ones used in class (pcs) for multi-thread operations. They do not expect a thread number. They expect a mode string only. Operation of method rm() of the client: --------------------------------------- This method has only two modes: gi : Get Image. Before calling method rm() at this mode, you must have a label control created into method setup() which will contain the image. Assign the label keyname to (cs) and assign a keyname to call the image with to (js) Both keynames must abide with PC# naming rules. Load the C# code required to generate the image into (os). The returned image will be displayed into the label control specified. Here are all parameters which you may supply to method rm("gi"): cs=Label keyname js=Image keyname os=C# code. i,o=Image width, height kb = Image Cashing flag. kb=true means no cashing. Image must be reproduced. ib = Image positioning flag. ib=true means absolute positioning. gt : Get Text. This mode is used when the data you want to get from the server is of any type other than image. You load the required parameters and mode for the method you like to call at the server in addition to the output variable(s) which you like to get back into (os) before calling rm("gt"). If you like to receive more than one output variable, list them seperated with commas. You will receive server's output assigned to the array OS[]. Each row of this array will contain the value of one of the output variables which has been requested. If an array was requested, it will come in the form "{row0,row1,row2,...}" Here is an example: The server method om("s") receives a string which contains several substrings seperated with a specific character and returns array OS[] which contains one substring in each row. It also outputs the number of substrings assigned to (oi) If called from code which runs at the server, the call would look like this: oc=',';os="apple,orange,banana";om("s"); and the output would be: OS[] containing "apple" into its first row, "orange" into its second row and "banana" into its third row. In addition to (oi=3) If we make the same call from the client, it would look like this: os="oc=,;os=apple,orange,banana;mode=os;out=OS,oi;";rm("gt"); The output you get from this call will be the JavaScript array OS[] with the following data into its first two rows: OS[0] contains: {apple,orange,banana} OS[1] contains: 3 As you can see, no delimiters are used within the input string (os). For example, it contains (os=,) not (os=',') as you may have expected. Variables must be assigned pure literal values, no other variables or operators are allowed within the assignments. (mode=os) since the method om()'s first char is 'o' and the mode string is 's'. (out=OS,oi) Means send us the resulting server side array OS[] and variable (oi) back. What should you have at the server? ----------------------------------- Before your program at the sever runs, class pasp checks to see if the client's request was for remote method access. If it was found to be, it handles it by itself and your program at the server never runs. If it was found to be a non-AJAX call or an AJAX call which is not for the purpose of remote method access, it calls method update, so your program at the server runs and executes the request. If your program expects AJAX calls, it should be constructed the same as in the previous example. If it finds that the request is not an AJAX one, it should reproduce the full page including all the scripts which run at the client. If the client scripts include a remote method call which accesses one of the special server side methods "m0():m9()", your program should include an override to that method. How many server methods and modes can be accessed remotely? ----------------------------------------------------------- If not for the security issue, every method can be accessed at all its modes. However for security reason, we are currently making some methods or modes inaccessable remotely. SECURITY CONSIDERATIONS: ======================== Allowing JavaScript to access PC# methods at the server is great, but it can cause security problem. You may like to say that the JavaScript code running at the client is written by yourself and you would not allow it to do something damaging to your server. This is unfortunately not enough. Hackers can replace your code at the client with theirs. For this reason we have made the following restrictions when PC# methods are called directly by the client: (1) Method fm() and method nm() are totally inaccessable remotely. (2) Method sm() is inaccessable except for the "Date and Time" modes. (3) Method gm() is accessable except for printing and saving the bitmap object to disk. (4) Method xm() is inaccessable at mode "r" which runs external programs. (5) Method tm() is inaccessable at modes starting with "E" which handle encryption. With these restrictions, your JavaScript code can still use class pasp to create all the rich graphics which it can generate. We hope that this would be satisfactory enough to you. Restrictions are hard wired into class pasp. If you like to disable remote access in full, you can e-mail us requesting a new copy of class pasp which does not allow remote calls. The special methods [m0():m9()] are considered to be the safer choice since they are at the server and hackers are not expected to be able to modify them using predictable means. Therefore these methods are allowed to use any PC# public method with no restriction. This does not mean that we encourage their extensive use. Nobody can tell for sure what hackers are capable of doing. Making these methods password protected or adding any other safety measures by yourself can be of great help. In the future we may develop a security protocol which allows you to set the restrictions by yourself. ========================================================================================= Example 7: This example includes a JavaScript code which runs at the client and makes two remote calls to methods at the server as follows: (1) A call to method sm() at mode "dt" which obtains current time at the sever. (2) A call to the special method m0() which creates the same playing card which was used in example 10 of WPDI. ========================================================================================= public partial class pg7:master1 { public override void init() { base.init(); } public override void setup() { base.setup(); // Run setup() of master page first //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 1 col, 2 rows cs="lb0";cis="ACCESSING SERVER'S METHODS REMOTELY USING AJAX";j=0;k=0;ds="c"; fns="trb14";cls="r0p7";wm("i"); // Title wm("o");ds="c";cls="b0";fns="trbi12"; os="When you place the mouse cursor on the first green rectangle, Method sm() at the"; os+=" server is accessed via AJAX and current time is requested. The received data is"; os+=" displayed at the same location.";wm("dp"); os+="When you place the mouse cursor on the second green rectangle, a special method"; os+=" at the server is called. That method uses method gm() to create an image of"; os+=" a playing card dynamically. The image is received at the client and displayed"; os+=" instantly.";wm("dp"); wm("c"); cs="lt0";j=0;k=1;wm("i"); // Description //----------------------------------- tb3 Contents ---------------------------------- cns="tb3"; // tb3 is made of 2 cols, 1 row cs="tb6";j=0;k=0;lf=180;of=240;ds="c";cls="r0g7";wm("i"); cs="tb7";j=1;k=0;lf=180;of=240;ds="c";cls="r0g7";wm("i"); //----------------------------------- tb6 Contents ---------------------------------- cns="tb6"; // tb6 is made of 1 col, 1 row cs="lb1";cis="Place cursor here."; ds="c";cls="S9g7";fns="trb14";wm("i"); //----------------------------------- tb7 Contents ---------------------------------- cns="tb7"; // tb7 is made of 1 col, 1 row cs="lb2";cis="Place cursor here.";ds="c";cls="S9g7";fns="trb14";wm("i"); } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; // If not Page_Load event return setup(); // Install all controls MakePage(table); // and make the page. PageNumber(7); // Set page number //-------------- At mouseOver, get the time from server and display it -------------- cs="tb6";ks="onMouseOver"; // When mouse is over tb6 do: os="os='os=;mode=sdt;out=os;';rm('gt');cs='lb1';cis=OS[0];cm('sl');"; //$ See comment at bottom. wm("js"); // Send script block. //--------------------- At mouseOut, restore original message ----------------------- cs="tb6";ks="onMouseOut"; // When mouse is outside tb6: os="cs='lb1';cis='Place cursor here.';"; os+="cm('sl');"; //$ Display original message into lb1 wm("js"); // Send script block. //----- At mouseOver, call m0() at server to generate card image & display it ------- cs="tb7";ks="onMouseOver"; // When mouse is over tb7 do: os="cs='lb2';js='im2';kb=true;"; //$ Label & image keynames, no cashing os+="i=100;os='mode=0';rm('gi');"; //$ width=100 px,os=code, get image. wm("js"); // Send script block. //--------------------- At mouseOut, restore original message ----------------------- cs="tb7";ks="onMouseOut"; // When mouse is outside tb7: os="cs='lb2';cls='S9';cm('sc');"; //$ Set foreground color to black. os+="cs='lb2';cis='Place cursor here.';"; //$ Create instruction msg. os+="cm('sl');"; //$ and display it wm("js"); // Send script block. } //------------------ Draw card (Method is copied from example 10, WPDI) --------------- public override void m0(string mode) { // Card's front drawing method lf=224;of=300;wm("bo"); // Open new bitmap operation using bitmap of // size 224 X 300 pixels. cls="p7";gm("ec"); // Paint background with same color as page cls="s9";gm("sps"); // Prepare solid white paint pen lf=224;of=300;gm("crf"); // Draw card's face rectangle cls="r0";gm("sps"); // Set color to pure red, solid pen/brush fns="trp24"; // Set font:TimesRoman, plain size=24 os="A";jf=-92;kf=130;gm("ctf"); // Draw the text "A" at top left os="A";jf=92;kf=-130;ad=180;gm("ctf"); // Draw same rotated 180 degrees // at bottom right corner. lf=of=30;ad=45;gm("crf"); // Fill a 30X30 square at card's center // rotated 45 degrees. jf=-92;kf=110;lf=of=12;ad=45;gm("crf"); // Do same but smaller at top left corner jf=92;kf=-110;lf=of=12;ad=45;gm("crf"); // and at bottom right corner wm("bc"); // Close bitmap operation } } ========================================================================================= COMMENTS: (1) The script which gets the time: os="os='os=;mode=sdt;out=os;';rm('gt');cs='lb1';cis=OS[0];cm('sl');"; may look to be confusing when you see the 3 (os)'s on a row. Let us start with the inner-most section: os=;mode=sdt;out=os; It does the same as: os="";sm("dt"); If the call was made from the server in addition to (out=os) which means send the resulting value of (os) back. In order to make method rm() of the client send this code to the server, we need to load it into the string (os) as follows: os='os=;mode=sdt;out=os;'; Before all, we need to send this script from the server to the client using the server method wm("js"), and this also requires loading it into string (os), so it ended to be: os="os='os=;mode=sdt;out=os;';......."; Remember that the inner-most code which is the C# code JavaScript is going to be sending back to the server is not delimited. The next code which is the JavaScript code is delimited with single quotes. The outer-most code which is C# code is delimited with double quotes. You can reduce the nesting by using JavaScript file. (2) The script which gets the image: os='mode=0'; also may require a comment. It does the same as: m0(""); if the call was made from the server. For regular methods the first character of the mode string is the first character of the method's name. For the special methods [m0():m9()] it is actually the second character of the method's name which is "0". We did not need to specify mode when we accessed m0() since it contains only one mode. So we used an empty string to access it with. This makes the combined mode which we supply method rm() with: (mode=0;)


========================================================================================== CALLING ANY C# METHOD REMOTELY: =============================== You can access any method remotely if you do few modifications to the method. Let us assume that you have this method at the server: public float AddTax (float Total, double TaxRate) { return (Total+(float)(Total * TaxRate / 100)); } Before you can access this method remotely by a JavaScript program at the client, you need to modify it as follows: (1) You need to change its name to one of the ten special method names [m0():m9()]. Always follow the new name with a comment which tells its original name. (2) You need to replace the two parameters with standard PC# method parameters which are: j k i o jf kf lf of jd kd id od ad jb kb ib ob js ks os cls fns fls ims urs Since the "Total" is float, you can replace it with any of (jf, kf, lf or of), and Since the "TaxRate" is double, you can replace it with any of (jd, kd, id or od) (3) You need to replace the return value with one of the following: o of od ob oy oc or ol os OS[] (4) You must reset all parameters used at the end of the method. To reset all GUV's at once, use om("c"); If you have decided to use m0() for the method name, (of) for both "Total" and the return value and to use (id) for the "TaxRate", your method will become: public override void m0(string mode) { // AddTax of=of+(float)(of*id/100); id=0; } The mode string is unused in this case. So you will use any dummy name for it when you call the method, an empty string can do this job just fine. So, to call this method from the server, use: m0(""); and to call it from the client use: os="of=...;mode=0;out=of;"; We have replaced the "Total before tax" with "...". In an actual application, it could either be a number to replace the 3 dots with or it could have been pre-assigned to a JavaScript variable. Assuming that the JavaScript variable is named (TotalBeforeTax), here is how your code should have been modified to: os="of="+TotalBeforeTax+";mode=0;out=of;"; The mode string can help you if you have more than 10 methods. You can make any number of methods share the same special method by assigning a different mode string to each one. You can also use the original name as the mode string. So you'll be calling m0("AddTax") from the server in this case. From the client, you'll be using: os="of=...;mode=0AddTax;out=of;". REMARK: ------- You may be wondering why the methods parameter list did not include (cs), (cis), (cus) or any other control setup parameter. The answer is that on a remote method call, method setup() of the server never runs. Remember that method setup() is called by method update() and that method update is not executed when a remote call is received. So, to the server, all controls are not available when a remote call is handled. This means that you cannot access wm("gu") remotely for example to get the text value of a text field. Such value must be obtained at the client using the JavaScript function cm("gu") instead. EXECUTING MULTIPLE REMOTE METHOD CALLS: ======================================= Remote method calls normally execute one method call at a time. You supply literal values to the remote method's parameters and expect to receive method's return value. In our case, parameters are not unique for each method and return values can be more than one. Your call is expected to be in the form: pars=..;mode=..;out=..; Whenever you like to execute more than one method, you include your code into one of the special server side methods [m0():m9()] and call that method remotely. In reality, this is not the only option. Our remote method invoker software can handle a series of method calls in the form: pars=..;mode=..;pars=..;mode=..;...............out=..; Although We still think that using a special method is the better choice, we'll show you how to write one JavaScript program which generates all the graphics it needs using help from methods of class pasp at the server. The program calls the server to execute all called methods once only at its end. We are going to be using the same code used in example 7, WPDI which is: =========================================================================================== lf=of=185;wm("bo"); // Open new bitmap operation using // bitmap of size 185 X 185 pixels cls="p7";gm("ec"); // Paint background same as page lf=of=150;gm("ce"); // Create a circle ks="effect_s";wm("vg"); // Retrieve the effects string if (os.Length<1) os=" "; // If var lost or corrupted use default //----------------------------- Radial Gradient Paint ------------------------------ if (os.Equals("RGP")) { // If "Radial Gradient Paint selected: cls="s9g0";gm("spr"); // Make radial gradient brush for the circle gm("grf"); // Render-fill the circle object. } //----------------------------- Linear Gradient Paint ------------------------------ else if (os.Equals("LGP")) { // If "Linear Gradient Paint selected: cls="s9r0";ad=0;gm("spl"); // Make linear gradient brush for the circle gm("grf"); // Render-fill the circle object. } //-------------------------- Special Effects - Reflection --------------------------- else if (os.Equals("SER")) { // If "Sp Effects-Reflection selected: of=5;cls="b0";ks="r";gm("grs"); // Render with sp effects-reflection // brightness factor=5, blue color } //----------------------------- Special Effects - Depth ----------------------------- else if (os.Equals("SED")) { // If "Sp Effects-Depth selected: cls="s9s0";id=20;ad=30;ks="d";gm("grs"); // Render with sp effects-depth // Shear angle=30, Depth=20 pixels } //---------------------------- No 3D Effects Requested ------------------------------ else { // If No Selection made (title selected): cls="p0";gm("sps"); // Create Pink solid paint brush gm("grf"); // Render-fill the circle object. } wm("bc"); // Close bitmap operation. ========================================================================================== Originally, user's choice has been delivered through session variables. Now, the code is going to be placed into a method named effects() and the user's choice will be its only parameter. All calls made to method gm() are made using literal values assigned to parameters. So, they all qualify as remote method calls, but what are we going to do with the "if" statements? The answer is that we are not going to execute them at the server. We are going to execute them at the client using JavaScript variables. We are going to be using a JavaScript file as we have done before, except that this time, we are not going to change the default JavaScript level (jsi), so both your script file and PC#'s script file will be available. ========================================================================================== Example 8: Create the same graphics which have been used in example 7, WPDI to show different 3D effects. Use a JavaScript file with remote method calls to the server this time. ========================================================================================== The JavaScript file (graphics.js): ---------------------------------- function mouseOver() { // Will run at "onMouseOver" event cs="tf0";cm("gu");os=cus;effects(); // Get selection, supply it to method } function mouseOut() { // Will run at "onMouseOut" event os=" ";effects(); // Select "No 3D required" } function effects() { // IN:os=3D effect. Can be: rgp, lgp, ser, sed. var o1s=os; // Save user's choice temporarely os ="lf=185;of=185;mode=wbo;"; // Open new bitmap operation using // bitmap of size 185 X 185 pixels os+="cls=p7;mode=gec;"; // Paint background same as page os+="lf=150;of=150;mode=gce;"; // Create a circle if (os.Length<1) os=" "; // If no selection found use default //----------------------------- Radial Gradient Paint ------------------------------ if (o1s=="rgp") { // If "Radial Gradient Paint selected: os+="cls=s9g0;mode=gspr;"; // Make radial gradient brush for the circle os+="mode=ggrf;"; // Render-fill the circle object. } //----------------------------- Linear Gradient Paint ------------------------------ else if (o1s=="lgp") { // If "Linear Gradient Paint selected: os+="cls=s9r0;ad=0;mode=gspl;"; // Make linear gradient brush for the circle os+="mode=ggrf;"; // Render-fill the circle object. } //-------------------------- Special Effects - Reflection --------------------------- else if (o1s=="ser") { // If "Sp Effects-Reflection selected: os+="of=5;cls=b0;ks=r;mode=ggrs;"; // Render with sp effects-reflection // brightness factor=5, blue color } //----------------------------- Special Effects - Depth ----------------------------- else if (o1s=="sed") { // If "Sp Effects-Depth selected: os+="cls=s9s0;id=20;ad=30;ks=d;mode=ggrs;"; // Render with sp effects-depth // Shear angle=30, Depth=20 pixels } //---------------------------- No 3D Effects Requested ------------------------------ else { // If No Selection made: os+="cls=p7;mode=gec;"; // Erase all. } os+="mode=wbc;"; // Close bitmap operation. cs="lb1";js="im2";kb=true;rm("gi"); // Get image remotely, no cashing. } The page file (pg8.cs): ----------------------- public partial class pg8:master1 { public override void init() { base.init(); } public override void setup() { base.setup(); // Run setup() of master page first //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 1 col, 3 rows cs="lb0";cis="EXECUTING MULTIPLE REMOTE METHOD CALLS ALL AT ONCE"; j=0;k=0;ds="c";fns="trb14";cls="r0p7";wm("i"); wm("o");ds="w";cls="b0";fns="trbi12"; os="Type the 3-letter code of wanted 3D effect then place mouse cursor at"; os+=" the right side of the page.";wm();wm(); os="rgp = Radial Gradient Paint.";wm();os="lgp = Linear Gradient Paint";wm(); os="ser = Special Effects - Reflection.";wm();os="sed = Special Effects - Depth.";wm(); wm("c"); cs="lt0";j=0;k=1;wm("i"); cs="tf0";cis="Type 3-letter code";j=0;k=2;ds="c";jf=20;cls="b0y0";fns="trbi12";wm("i"); //----------------------------------- tb3 Contents ---------------------------------- cns="tb3"; // tb3 is made of 1 col, 1 row cs="lb1";//cis="Type your password then place the mouse cursor anywhere here."; j=0;k=0;ds="c";ls="s9o0";fns="trb14";wm("i"); } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; // If not Page_Load event, exit. setup(); MakePage(table); PageNumber(8); fls="graphics.js";wm("jf"); // Send Script File cs="tb3";ks="onMouseOver"; // When mouse cursor is on tb3: os="mouseOver();";wm("js"); // run function mouseOver() (in file) cs="tb3";ks="onMouseOut"; // When mouse cursor is out of tb3: os="mouseOut();";wm("js"); // run function mouseOut() (in file) } } ============================================================================================= COMMENTS: ========= (1) We kept JavaSript level (jsi) at 1. So, we could use the helpful PC#'s JavaScript functions. Additionally, we used our own JavaScript file which contains 3 JavaScript functions: function mouseOver(): Called when user places the mouse pointer on (tb3) It reads user's selection and calls function effects() to execute it. function mouseOut() : Called when user places mouse pointer outside (tb3) It calls function effects() supplying it with the selection (os=" ";) which causes the function to erase (tb3) function effects() : Uses remote method calls to the server to get the drawing which the user has selected or erase the table if the selection it received was (os=" ";) You must have noticed now that the only code missing is the JavaScript code which calls function mouseOver() when the user places the mouse pointer on (tb3) and the one which calls function mouseOut() when the user moves the pointer away. We could not have added them to the file since the file is executed before the page is loaded but they should be executed when events take place on (tb3) So, we used method wm("js") to send them to the client since this method knows how to put them at the correct place within the page. To know more about this subject, read "PC# reference-web" under the title "SENDING A SCRIPT BLOCK". (2) When function effects() is called, it gets user selection assigned to (os), this is JacaScript (os) The method needs to use this same variable to assign the remote calls parameters and modes to before it sends them to the server using function rm("gi") This is why it started by copying it to the local variable (o1s) and used this new variable to condition for the wanted drawing. ============================================================================================


========================================================================================== POSITIONING OBJECTS ON THE SCREEN ================================= When we showed you how to install controls into a desktop form using method cm(), we told you that the easiest and most convenient way to position the controls would be by making all your measurments relative to the form's center. This method have proven to do even better when we started creating graphics using method gm(). No matter if we use cartesian or polar coordinates for the drawings, the center of the form is always the center point of the drawings. This is the natural and scientific way to draw. When we started using method wm() to create web controls, things became different. We used tables to install the controls into. Table cells naturally start at the top left corner of the table and go toward the right horizontally and toward the bottom vertically. So we based our installation on this new way. One more reason for not using the form's center as the default position for web controls is that web pages normally occupy many screen frames and users use the scrollbars to move through them. This makes the form's center dependant on the scrollbars positions and we have no way to know where the scrollbars are set at since the page is created at the server while the scrollbars are set at the client. However, whenever we add drawings to a web page, we use method gm() so the drawings are made relative to the center of the web control which receives them. Finally, when we do positioning at the client using JavaScript we no longer have the same problems which we had when we have been working on the page at the server. More specifically: (1) We no longer use tables, we normally use absolute positioning. (2) We can tell where the scrollbars are at, so we can compensate for their positions. So, now it is time to return back to the original more convenient way. The JavaScript function cm("sB") does this job for you automatically. It expects the following parameters: j,k : Wanted new position in pixels of object's center relative to visible screen's center. i,o : Width and height of the object. kb : Scroll compensation flag. kb=true means compensate for scrollbars positions. Notice that (i,o) are necessary even if we are not changing the size. This is because they are used to calculate the new position. Personal C# Timer: ================== This timer is available in method um() at mode "t" of both classes, pcs and pasp. A JavaScript version is also available. Operation is identical for all versions. We are going to use this timer in the next example, so let us learn how it works. The timer counts time in milliseconds. It counts upto one minute (60,000 milliseconds) then it resets back to zero. The time count is returned into (ol). Each time you call the method, it returns to you the amount of time which has passed since a reference time. You can make the time the call is received a new reference time by supplying (ib=true) to the method. Let us have some examples to clear things up. (1) Assume that at one moment um("t") received this call: ib=true;um("t"); It will use this moment's time as a reference for future calls. (2) One second later it received this call: um("t"); It will return (ol=1000) since 1000 ms has passed since ref. time. (3) One second later it received this call: ib=true;um("t"); It will return (ol=2000) & replace old ref with this moment's time. (4) One second later it received this call: um("t"); It will return (ol=1000) since the new ref will be used. In other words, the time the method returns assigned to (ol) is the time elapsed since last call when (ib) was true. =========================================================================================== Example 9: Create an image control and make it stay always at the center of the visible part of the page regardless to scrollbars positions. Also create a transparent label control and place it at random within the visible part of the page. The label control will appear only when the user places mouse cursor within its borders. The random positioning of the control will be redone each time a scrollbar is activated. How fast will the user find the label? Let us make this a game and display the score at the moment the label is found. The time counter resets and starts counting when page is loaded and each time a scrollbar is activated. =========================================================================================== public partial class pg9:master1 { public override void init() { IsSingleTable=true; // Request Single Table Page. base.init(); } public override void setup() { base.setup(); //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 1 col, 4 rows wm("o");ds="nw"; cls="p0";fns="trb14";os="SCROLL INDEPENDANT POSITIONING: ";wm("d"); cls="b0";fns="trbi12";os="Notice that no matter where you move the scrollbar, the image"; os+=" stays at the same position relative to the visible portion of the page.";wm();wm(); cls="p0";fns="trb14";os="FIND THE MAGIC LABEL: ";wm("d"); cls="b0";fns="trbi12";os="This is a game, but it can be used to develop more serious"; os+=" applications. The magic label is invisible since it is fully transparent. It is"; os+=" placed within the visible portion of the page at random.If you place mouse cursor "; os+="where it is, it will appear to you. The time it takes you to find it in milliseconds"; os+=" will be displayed as your score. Each time you move the scroll bar, it changes "; os+="place so you can play a new game.";wm();wm(); wm("c"); cs="lt0";j=0;k=0;wm("i"); // Literal control for the text. cs="lb1";j=0;k=1;wm("i"); // Label controls for the Magic Label. cs="lb2";j=0;k=2;wm("i"); // Label control for the image. cs="lb3";j=0;k=3;wm("i"); // Label control for the score. } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; setup(); MakePage(table); PageNumber(9); //-------------------- Creating Magic Label, Image & Score label ------------------- wm("o"); // Open a new html loading operation. cs="lb5";os=" ";ib=true; // Create new label control into lb1 using i=85;o=80;cls="r09y00";fns="es22"; // absolute pos. and transparent background wm("db");wm("c");cs="lb1";wm("sl"); // Close loading operation and set (cis) wm("o"); // Open a new html loading operation. cs="im2";ims="../images/flower.jpg"; // Create new image control into lb2 Using ib=true;i=85;o=100;jd=5;wm("di"); // abs positioning, 5 pixels border. wm("c");cs="lb2";wm("sl"); // Close loading operation and set (cis) wm("o"); // Open a new html loading operation. cs="lb6";ib=true;jd=5; // Create new label control into lb3 using os="Find the Magic Label and see your score."; i=290;o=30;cls="r09g79";fns="trb12"; // abs positioning and lt green background wm("db");wm("c");cs="lb3";wm("sl"); // Close loading operation and set (cis) //-------------------- Position all controls when page is loaded ------------------- cs="pl";ks="pl"; // At page loading event do: os="position();"; //$ Call the function position(). wm("js"); // Send the script block. //--------------------- What to do when magic label is found ----------------------- cs="lb1";ks="onMouseOver"; // When mouse is over "lb1" do: os="cs='lb5';cis='Magic Label';cm('sl');";//$ Set the magic label's text os+="um('t');"; //$ Get time which has passed since last call os+="cis='Magic Label found in '+ol+' Milliseconds.';"; os+="cs='lb6';cm('sl');"; //$ (executed within position()) Display msg. wm("js"); // Send the script block. cs="lb1";ks="onMouseOut"; // When mouse is outside "lb1" do: os="cs='lb5';cis=' ';cm('sl');"; //$ Erase magic label's text. wm("js"); // Send the script block //----------------- Position all controls when scrollbar activated ----------------- cs="pl";ks=""; // Place this script at page end: os="window.onscroll=position;"; //$ When scrollbars activated call position() wm("js"); // Send the script block //---------------------------- Function to do positioning -------------------------- cs="";ks=""; // Place this script at page top: os ="function position() {"; //$ A function to position Image, score label //$ and Magic label. os+=" cs='im2';j=k=0;i=85;o=100;"; //$ Scale & Position image control at center. os+=" kb=true;cm('sB');"; //$ Compensate for scrolling. Position Image. os+=" cs='lb6';j=0;k=-85;i=290;o=30;"; //$ Position score label 85 pixels below center. os+=" kb=true;cm('sB');"; //$ Compensate for scrolling. Position Label. os+=" um('mr');od=od*680;var j1=od-340;";//$ Get a random no. in the range -340:+340 os+=" um('mr');od=od*340;k=od-170;"; //$ Get a random no. in the range -170:+170 os+=" cs='lb5';j=j1;i=85;o=80;"; //$ Use random no's as horiz & vert positions os+=" kb=true;cm('sB');"; //$ Compensate for scrolling. Position M. Label. os+=" ib=true;um('t');"; //$ Use current time as reference. os+=" cis='Find the Magic Label and see your score.';"; os+=" cs='lb6';cm('sl');"; //$ Change the score label display. os+="}"; wm("js"); // Send the script block } } =========================================================================================== COMMENTS: --------- (1) We hope that creating an image or a label into the text of another label does not confuse you. It has been discussed before. The carrier label is a regular web control which is mounted into a table cell. The other label is created by the html which (cis) of the carrier label contains. It's positioning is absolute so JavaScript at the client can set it on the screen wherever it should be. (2) Look at the scripts which execute at "onMouseOver" and "onMouseOut" events. We have two label controls lb1 and lb5. The first one is the one specified for the two events since lb5 cannot be used. Method wm("js") does not recognize it as a web control. However, lb5 inherits lb1's attributes. This is why it reacts to the two events no matter where it goes through the page. (3) The script which handles the "onscroll" event also deserves a comment. We made a function named position() to handle the event and inserted the following script at page end: window.onscroll=position; Notice that only the function name without '()' and without quotes is used. The function can be placed anywhere into the page although the page top and a script file are the two best and most commonly used places.


========================================================================================== CREATING CUSTOM DIALOG BOXES AT THE BROWSER =========================================== Do you remember examples 9 and 10 of the "desktop controls" section where we showed you how to create custom dialog boxes which can contain any combination of text, images and drawings? Can we do the same at the browser using JavaScript? Sure we can. It should be great to be able to create a better looking and performing dialog boxes which can replace the built-in ones. But unfortunately, there are some few problems. POPUP BLOCKERS: =============== JavaScript allows us to create subwindows which can be used as dialog boxes. Unfortunately, there are always the bad guys who abuse everything. People have been complaining of the large number of unwanted windows (refered to as popups) which are created without their permission. So, several companies have developed "popup blockers" which prevent the creation of subwindows. If you have installed one on your browser, you may need to turn it off in order to be able to view the next example. HOW TO CREATE A SUBWINDOW: =========================== Method cm() at mode "wo" can open a new subwindow for you. The parameters are as follows: j,k : Location of the subwindow's center relative to the screen's center. i,o : Width and height of the subwindow. js : Subwindow's name (optional). kb : Scrollbars availability. kb=true means install scrollbars on the subwindow. cis : Can be loaded with html and be used as the new subwindow's body. If you are going to assign a web page URL to (urs), keep cis="" since the web page will be the body. urs : Can be assigned the URL of a web page which will populate the new subwindow. If you are not going to populate the subwindow with a web page, keep urs="". THE WINDOW OBJECTS: =================== Normally, if we are not creating subwindows, there is only one window object which is used internally by PC#'s script to do many operations on the page. That object is refered to by (window) Remember, this is not a PC# name. It is the JavaScript name for the object of the window which contains the page. Personal C Sharp has added two more window ref names: wnp : The present window object. The main window assigns this name to the last subwindow object which it has created. wna : The opener window object. The new subwindow assigns this name to the main window object which has created it. To make sure you understand that, note the following: (1) Both the main window and the subwindow refer to their own objects by (window) (2) The main window refers to the subwindow's object by (wnp) (3) The subwindow refers to the main window's object by (wna) The name (wnp) is assigned automatically when the main window calls cm("wo") to create the subwindow. The name (wna) is not assigned for you. You must include the statement: wna=this.opener; into a script which runs at the start of the subwindow's page. COMMUNICATION BETWEEN THE TWO WINDOWS: ====================================== The subwindow can access any of the main window's resources using the (wna) reference name. For example variable (x) of the main window can be assigned the value (5) by the subwindow using the statement: wna.x=5; POSITIONING AND RESIZING WINDOWS: ================================= The main window sets a startup position and size for the subwindow when it creates it. After that, we like each window to take care of repositioning and resizing itself by its own. This is how PC# software is set. Try to abide with these rules in order to maintain simplicity and to minimize errors. To position a window: --------------------- Call cm("wp"). Its parameters are as follows: j,k : Location of calling window's center relative to the screen's center. Remember that we are expecting calling window to be the window to operate on also. i,o : Width and height of calling window. Required for center positioning. kb : "Adjust for Scrolling" flag. kb=true means adjust for scrolling. To size a window: ----------------- Call cm("wsf") if you like the window to occupy the screen in full. Call cm("wsc") if you like the window to occupy the client size of its containing window, Call cm("ws") if you like to specify a size in pixels. If you use this mode, supply: i,o : Wanted width and height of calling window. CLOSING WINDOWS: ================ (1) To close the subwindow by itself: self.close(); (2) To close the subwindow by the main window: wnp.close(); (3) To close main window, use window.close(). The browser will get permission from the user before it executes your order. To check to see if there is a popup blocker available: ------------------------------------------------------ The conditional statement: if (wnp) returns true if the new window has been launched successfully. If it returns (false) you can assume that a blocker is available. You can also use this condition to learn if the user has already closed the subwindow or not in a statement like this: if (wnp) wnp.close(); ========================================================================================== Example 10: Duplicate page 8 which displays graphics with the exception that the graphics show into a dialog box instead of being displayed on the page. Also, show how to create text dialog boxes which can display text with variety of colors and fonts in addition to images. ========================================================================================== Page 10 Class: -------------- public partial class pg10:master1 { public override void init() { base.init(); } public override void setup() { base.setup(); // Run setup() of master page first //----------------------------------- tb2 Contents ---------------------------------- cns="tb2"; // tb2 is made of 2 cols, 2 rows wm("o");ds="c";fns="trb14";cls="r0p7";os="CREATING CUSTOM DIALOGS";wm(); ds="w";cls="b0";fns="trbu12";os="If you have a popup blocker you must turn it off first."; wm();wm(); ds="c";cls="r0";fns="trb12";os="Using a dialog box to display page 8's graphics";wm(); ds="w";cls="b0";fns="trbi12"; os="rgp = Radial Gradient Paint.";wm();os="lgp = Linear Gradient Paint.";wm(); os="ser = Special Effects - Reflection.";wm();os="sed = Special Effects - Depth.";wm(); wm("c"); cs="lt0";j=0;k=0;i=2;wm("i"); cs="tf0";cis="Type 3-letter code";j=0;k=1;ds="s";jf=20;cls="b0y0";fns="trbi12";wm("i"); cs="bt0";cis="Submit";j=1;k=1;ds="sw";cls="r0g7";fns="trb12";wm("i"); //----------------------------------- tb3 Contents ---------------------------------- cns="tb3"; // tb3 is made of 2 cols, 2 rows wm("o");ds="c";fns="trb14";cls="r0p7";os="CREATING TEXT DIALOGS";wm(); ds="w";cls="b0";fns="trbu12";os="If you have a popup blocker you must turn it off first."; wm();wm(); ds="w";cls="b0";fns="trbi12"; os="d = Display only dialog.";wm();os="y = Yes / No dialog.";wm(); os="i = Input dialog.";wm();wm(); wm("c"); cs="lt1";j=0;k=0;i=2;wm("i"); cs="tf1";cis="Type 1-letter code";j=0;k=1;ds="s";jf=20;cls="b0y0";fns="trbi12";wm("i"); cs="bt1";cis="Submit";j=1;k=1;ds="sw";cls="r0g7";fns="trb12";wm("i"); } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; // If not Page_Load event return setup(); // Install all controls MakePage(table); // and make the page. PageNumber(10); // Set page number //-------------------- Global variable and function definitions -------------------- cs=ks=""; // At page top do: os="var txt='';"; //$ Define new string variable (txt) and a os+="function grCode() {cs='tf0';cm('gu');}"; //$ function to read tf0's text into (cus) os+="function receiveText() {"; //$ Define a function to receive dialog's os+=" window.alert('You have entered: '+os);"; //$ output and display it. os+="}"; //$ End of function. wm("js"); // Send script block. //--------------------- Creating the Graphic dialog box's window -------------------- cs="bt0";ks="onClick"; // When bt0 is clicked do: os="if(wnp) wnp.close();"; //$ If last dlg box was not closed, do it. os+="j=k=0;i=o=225;"; //$ open new subwindow of size 225X225 at os+="cis='';urs='grDialog.aspx';cm('wo');"; //$ center and load a web page into it. os+="return false;"; //$ DO not submit form to server. wm("js"); // Send script block. //----------------------- Creating the Text dialog box's window ---------------------- cs="bt1";ks="onClick"; // When bt1 is clicked do: //------ Step 1: Prepare text to be displayed on the new dialog ------ // It assigns it all to the main window variable (txt) os ="cm('o');"; //$ Open a new html loading operation. os+="ims='../images/icon.bmp';cm('hi');"; //$ Display PC# icon's image. os+="cls='r0';fns='trb14';ds='c';os='MENU';cm('hl');"; //$ Display title in red at center. os+="cls='S9';fns='trb10';ds='w';cm('hp');"; //$ Change color, font. Move to new parag. os+="os=' (R) Red.';cm('hl');"; //$ Display menu lines... os+="os=' (G) Green.';cm('hl');"; //$ Remember, all html is loaded into os+="os=' (B) Blue.';cm('hl');"; //$ the string variable (cis) os+="os=' (E) Exit.';cm('hl');cm('hl');"; os+="cls='b0';os='Selection :';cm('hl');"; os+="cm('c');"; //$ Close loading operation. os+="txt=cis;cis='';"; //$ Assign html generated to (txt) //------ Step 2: Create the text dialog box which user has selected ------ os+="if(wnp) wnp.close();"; //$ Close last dialog box if not closed os+="cs='tf1';cm('gu');"; //$ Read user selection into (cus) os+="j=k=0;i=o=325;cis='';"; //$ open new subwindow of size 325X325 at os+="urs='txDialog.aspx?dlg='+cus;"; //$ center. Assign text dialog to (urs) os+="cm('wo');"; //$ after attaching type as a query string os+="return false;"; //$ DO not submit form to server. wm("js"); // Send script block. } } ========================================================================================== Graphic dialog: --------------- public partial class grDialog:pasp { // pasp extended directly. No master pge public override void init() { base.init(); } public override void setup() { //---------------------------------- Page Contents ----------------------------------- cns=""; cs="tb0";cls="S9g8";fns="trb12";wm("i"); // Root table. //----------------------------------- tb0 Contents ----------------------------------- // Function effects() (See example 8) which will be used to create the graphics,loads // the graphics into (cis) of a label named (lb1) So we should create a label with // same name here. Will load (cis) with default text to show up if operation was not // successful. If successful, this text will be overwritten with graphics. cns="tb0"; cs="lb1";cis="Type a 3-Letter code then click on the Submit button."; j=0;k=0;ds="c";ls="s9o0";fns="trb14";wm("i");// Label which will contain the images. } //------------------------------------------------------------------------------------ public override void update() { if (!cs.Equals("pl")) return; // If not Page_Load event, exit. setup(); MakePage(table); fls="graphics.js";wm("jf"); // Send Script File. This is the same // file used for page 8. cs="pl";ks=""; // After page is loaded do: os="wna=this.opener;"; //$ Assign main window object to (wna) os+="wna.grCode();os=wna.cus;"; //$ Run grCode() of main window, assign os+="effects();"; //$ user selection to (os), then run //$ function effects() (in script file) wm("js"); // Send script block. } } ========================================================================================== Text dialog: ------------ public partial class txDialog:pasp { // pasp extended directly. No master pge string dlg=""; // Define a string to be assigned // selected dialog type code. public override void init() { base.init(); } public override void setup() { //---------------------------------- Page Contents ----------------------------------- cns=""; cs="tb0";cls="S9p8";fns="trb12";wm("i"); // Root table. //----------------------------------- tb0 Contents ---------------------------------- // This page comes with query string which determines the type of dialog to draw. // Method update() will assign the type to string (dlg) before setup() starts. cns="tb0"; cs="lb1";cis="Type a 1-Letter code then click on the Submit button.";j=0;k=0;i=2; ds="c";cls="s9o0";fns="trb14";wm("i"); // Label to display received text. if (dlg.IndexOf("i")==0) { // If "Input dialog" selected: cs="tf0";j=0;k=1;ds="s";jf=20;cls="b0y0";fns="trbi12";wm("i"); cs="bt2";cis="OK";j=1;k=1;ds="sw";cls="r0g7";fns="trb12";wm("i"); } // create text field and a "OK" button. else if (dlg.IndexOf("y")==0) { // If "Yes/No" dialog selected: cs="bt0";cis="Yes";j=0;k=1;ds="s";cls="S9g7";fns="trb12";wm("i"); cs="bt1";cis="No";j=1;k=1;ds="s";cls="S9r2";fns="trb12";wm("i"); } // create 'yes' and 'no' buttons. else { // If "Display only" dialog selected: cs="bt2";cis="OK";j=0;k=1;ds="s";cls="r0g7";fns="trb12";wm("i"); } // create "OK" button only. } //------------------------------------------------------------------------------------- public override void update() { if (!cs.Equals("pl")) return; // If not Page_Load event, exit. ks="dlg";wm("rq");dlg=OS[0]; // Get value of (dlg) from query string setup(); MakePage(table); //--------------------- Initialization and function definitions -------------------- // function send(): Receives text in (cus), assigns it to (wna.os) then calls // function wna.receiveText() Then it closes dialog box. cs="";ks=""; // At page top do: os ="wna=this.opener;"; //$ Assign main window object to (wna) os+="function send() {"; //$ Define a function to send user's text os+=" wna.os=cus;"; //$ Assign (cus) to main window's (os) os+=" self.close();"; //$ close this subwindow. os+=" wna.receiveText();"; //$ Run receiveText() of main window. os+="}"; //$ End function. wm("js"); // Send script block. //--------------------------- Display dialog box's body text ------------------------- // Displays the text assigned to (wna.txt) then resizes windw to the text size. // See comment at bottom. cs="pl";ks=""; // At page end do: os ="cis=wna.txt;cs='lb1';cm('sl');"; //$ Get text from main window, display it. os+="cs='tb0';cm('gBW');var i1=o+40;"; //$ Assign (tb0)'s width +40 to (i1) os+="cs='tb0';cm('gBH');var o1=o+100;"; //$ Assign (tb0)'s height +100 to (o1) os+="i=i1;o=o1;cm('ws');"; //$ Resize this subwindow to (i1,o1) os+="cm('wwc');om('ti');i1=o;cm('whc');om('ti');o1=o;"; //$ Get dialog's final width & height. os+="j=k=0;i=i1;o=o1;cm('wp');"; //$ Position this subwindow at center. wm("js"); // Send script block. //---------------------- Handling dialog box's button click events ------------------- // Gets text entered into input dialog box assigned to (cus) and calls local function send() // which sends it to wna.receiveText() to display it. For Yes/No dialog box, it assigns // "Yes" or "No" to (cus) and does the same. For Display dialog box it just closes it. if ("di".IndexOf(dlg)>-1) { // If "display only" or "input" dlg: cs="bt2";ks="onClick"; // If "OK" button clicked: if (dlg.IndexOf("i")==0) { // If came from input dialog box: os="cs='tf0';cm('gu');send();"; //$ Send tf0's text to main window. } else os="self.close();"; //$ Else, just close this subwindow. os+="return false;"; //$ DO not submit form to server. wm("js"); // Send script block } else { // Else if "Yes/No" dlg on display: cs="bt0";ks="onClick"; // If "Yes" button clicked: os="cus='Yes';send();"; //$ Assign "Yes" to (cus) os+="return false;"; //$ DO not submit form to server. wm("js"); // Send script block cs="bt1";ks="onClick"; // If "No" button clicked: os="cus='No';send();"; //$ Assign "No" to (cus) os+="return false;"; //$ DO not submit form to server. wm("js"); // Send script block } } } ========================================================================================== Running this page requires the 4 files to be available at your application folder: (1) graphics.js (The same one used with page 8) (2) pg10.cs (3) grDialog.cs (4) txDialog.cs Additionally, the 3 ".cs" files must be compiled using "pcw" tool generating the 3 additional files: pg10.aspx, grDialog.aspx and txDialog.aspx. COMMENTS: --------- (1) We wanted to resize the text dialog boxes so they become large enough to take their contents plus some extra for margins, so we used the following strategy: a) We did not specify a size for (tb0) which is the container of everything inside the dialog box. As you know, when the browser finds that a container is not large enough for its contents, it neglects our size and does the sizing job by itself. It makes it just enough to take whatever is in it which is exactly what we want. b) The next step was to resize the subwindow to a slightly larger size than (tb0) in order to allow for 4 margins. (3) Note that we ended each script block which handles the onClick event of a button with "return false;". That was necessary in order to prevent submitting the form to the server.