Previous Thread
Next Thread
Print Thread
Rate Thread
Page 1 of 2 1 2
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
The following post is a tutorial on writing new hacks for the 6.6 control panel. At the end there is a brief set of instructions that will walk you through installing a new page.

Even if you don't understand all of the concepts the code uses (references and the like), please try to follow the way things work.

Please post any questions you have, I'll be glad to answer'em. smile

-------------------------------------

The main new feature in UBB.classic 6.6 is the new control panel. The UI was designed to mimic the look and feel of the new UBB.x and Eve platform control panels - a menu on the left, DHTML tabs on the top, with a dash of DHTML magic where appropriate.

As with very many "second hand" features (such as the Avatar implementation taken right from UBB.x), I had the advantage of knowing all of the downsides and potential gotchas of the DHTML tab system before implementing it. Knowing the potential problems lead me to a single conclusion - the existing control panel code could not be smartly adapted to the new UI.

The old control panel code made too many assumptions about how navigation worked (it didn't), which elements of which pages belonged where, etc, etc. Adapting it to think how it needed to think would have been just as much work as creating new code.

Before adding new code or areas, it is critical that you understand how the control panel thinks and works.

Each area of the control panel is a page. Each page has one or more tabs. A request to cp.cgi?page=primary;tab=email would go to a page called "primary" and a tab called "email."

The page and tab determine which sets of libraries and templates get loaded. Let's walk through the above request to cp.cgi.

After authentication, the menu definition for your user status is loaded. There are different menus for admins, moderators, and users that have yet to log in. If the requested page is not available in the menu, an error is thrown. If the page is available, a check is made for a page subroutine with the passed page name - "cp2_page_primary" in this case. If the subroutine exists, it's executed and takes over. If not, a check for the page and tab is made: "cp2_page_primary_tab_email"

If NEITHER subroutine was found, checks are made for template files for that page and tab. In this case, the two templates would be "cp2_primary" and "cp2_primary_tab_email." If they are found, they are loaded. If there are multiple tab templates, only the main template and the one tab we're looking for are loaded. In our case, let's assume that only cp2_primary exists.

Each template contains at least three subroutines. Examples in this case would be "cp2_template_primary_init" "cp2_template_primary_libs" and "cp2_template_primary_run"

The libs subroutine is expected to return a list of libraries required to run the page in question. For our example, the libs subroutines returns a one element array, containing "cp2_vars", meaning cp2_vars.cgi is to be loaded.

After the libs subroutine is executed, the init subroutine is expected. Init may perform any additional tasks that need to be run when the template loads.

The run subroutine is expected to return an array containing strings of HTML - one element per page tab. A run subroutine that generates a page with three tabs would return three elements in the array.

Back to the task at hand. Once the template is loaded (and any libraries required are loaded), another check is made for a page subroutine or the page/tab subroutine. The page code should be in the loaded libraries. In our case, the cp2_vars.cgi file contains our page subroutine.

When the proper subroutine is found, it's called. If no subroutines could be found at this point, an error is thrown.

That brings us to the basic assembly of page routines.

Each page subroutine normally has four distinct parts:

Code
sub cp2_page_primary {

# Part 1: Setup

if($in{d} eq "submit") {
# Part 2: Form submission. This may be passed off to another subroutine.
&GetOrPost("POST");

@example = split(/n/, $in{new_example});
&WriteFileAsArray("example.cgi", @example);

$in{returnpage} = $in{page};
$in{returntab} = 0;
&StandardHTML("Done.", { back_button => -2 });
} # end if

# Part 3: Form preparation
my @example_file = &OpenFileAsArray("example.cgi");

# Part 4: Print the form
print &WrapContent(
&WrapTabSet(
{},
[&cp2_template_primary_run(@example_file)],
undef, undef, [],
)
);
exit;
} # end cp2_page_primary
The code in part 1 is always executed when the page is called, even when it's a form being processed. This is the place to check arguments, load code or data, etc.

Part 2 is generally an if block that checks to see if this is a form submission, or what kind of form submission is happening. Determining the state of a form is usually left to the "d" paramater to the script. A value of "submit" is used to denote a normal submit action, while other values can be specified by the form you create. The exact methodology is left up to you. Some current pages use "setter" instead of "d".

The end of part 2 is generally a call to StandardHTML with a confirmation message. More information on the new options that StandardHTML can take is below. If the form submit was a partial success or a failure, you can either throw StandardHTML or continue running and pass an error out as part of the normal page content. See sub AutoVars and the real cp2_page_primary in cp2_vars.cgi for example code.

If this isn't a form submit, or there were errors during the form submit and you didn't throw StandardHTML, the code in part 3 is run.

Finally, we print the form and exit. This is done by calling two subroutines.

&WrapContent returns the passed HTML attached to the standard control panel header and footer.

&WrapTabSet is more interesting. It takes five possible arguments:
  • A hashref with arguments for a page form (see code for calling method)
  • An arrayref, each element containing the HTML for one tab on the page
  • A string with an "override" page name for the menus and breadcrumbs
  • A string with an "override" tab name
  • An arrayref that contains arrayrefs that contain hashrefs that define any lower tabs that may be required on each tab.


That last argument has probably confused you.

Actions to be performed on the task at hand are attached to each tab using tabs at the BOTTOM. These bottom tabs are defined on a tab-by-tab basis, meaning DHTML tab 1 may have a different set of bottom tabs than DHTML tab 2, if at all. Thus, to get tabs at the bottom of the second DHTML tab, but not the first or third, the following arrayref would be passed:

Code
[
[], # first tab
[
{
name => "Bottom Tab",
url => "$vars_config{CGIURL}/$CONTROLPANEL",
},
], # second tab
[], # third tab
];
There may be a maximum of three bottom tabs per DHTML tab. Sizes are fixed to about 30%, so be careful about wording.

The last three arguments to &WrapTabSet are optional and may be excluded entirely. You will often see short calls that only define the first two arguments:

Code
print &WrapContent(&WrapTabSet({}, [&cp2_page_whatever_run()]));
The first argument to &WrapTabSet can also be a point of confusion.

Forms can apply to the page in two ways. First, a form may submit everything on the page, meaning that everything in every tab belongs to the same form. Second, a form may submit only everything on that one tab. In the second mode, each individual tab would have its own form.

The form arugments to &WrapTabSet create page-wide forms. To create tab-specific forms, use the "formstart" and "formend" components (via &MakeComponentHTML, which we'll learn about shortly).

This is a good place to talk about the new arguments to StandardHTML. Beyond the message to be posted, StandardHTML can take any of the following arguments in a hashref:

  • redirect_title - combine with redirect_url to create a forwarding page... title of "Continuing..." link
  • redirect_url - URL that link returns to / URL to forward to, if redirect_title is used
  • redirect_delay - seconds to wait if this is a redirect page (redirect_title and redirect_url passed)
  • override - force a page name (for tab only - does NOT change navigation)
  • overtab - force a tab name
  • back_button - title for the "Return" link... use w/ redirect_url for messages rather than forwards,
    or alone without a redirect_url for wording alone...
    ... *OR* one of three numbers:
    • 0 - do not display "return" link/title
    • -1 - return to control panel home
    • -2 - attempt to determine the page and tab we were on using magic vars created by
      a page form. Set $in{returnpage} and $in{returntab} manually if a page form wasn't used.

  • [*]extra_qs - hashref of additional arguments for return link, if back_button is -2

When back_button is passed -2, StandardHTML blindly assumes that the current request came from a page based form rather than a tab based form. The page based form includes two hidden fields - "returnpage" and "returntab" - that are generated based on the currently selected tab. These hidden fields are not created when using tab based forms. To "smartly" use -2 after a tab based form submit, you must set them yourself (either in the form or before calling StandardHTML).

(Yes, this all seems very obtuse... The prototype code ended up working well enough that it turned into the real thing far before I realized what was happening. Oops. Apologies for the stupidity. At least it works and I can still hack at it. smile )

Okay, so in review of what we have so far...

  • Menu sets determine what users can get to
  • All accessable areas are in PAGES and TABS
  • Pages and tabs are executed via library code
  • Library code is loaded by the templates
  • Templates (and thus library code) are loaded on demand based on the requesting page
  • There's a generic model for a page handling sub that can be easily cloned


There are two remaining general areas that you need to know about. First, you need to know how to actually make the HTML that gets stuck into each tab on the page.

Above I refered to a subroutine named MakeComponentHTML. &MakeComponentHTML itself takes two arguments: a hashref containing a list of &Template substitutions (for replacing %%TEMPLATE%% strings in the resulting HTML), and an arrayref containing hashrefs that build the actual HTML.

I don't recall actually ever using the &Template hashref. Most calls you'll see to &MakeComponentHTML look something like:

Code
return &MakeComponentHTML({}, [
{
type => "header",
title => "Hello, world!",
},
]);
Each of the hashrefs has to have a "type" key with a valid component type. Available types are:

Listables:
----------
-checkbox
-multichecks
-radio
-selectlist
-selectlistplustext

Text Input:
----------
-regfieldselect
-text
-textarea

Other Form Components:
----------
-confirmprompt
-customtitles
-datebox
-formend
-formstart
-hiddenfield

Expandy Bits:
----------
-expandybuffer
-expandycheckbox
-expandyheader

Other:
----------
-generic
-halfandhalf
-header
-raw
-twocellwrapper

There are some generally common arguments (name, title, class/classleft/classright). All listables can take an options argument that contains the list of available options (i.e. a list of forums as generated by &MakeForumSelectList).

Other than those noted, EACH COMPONENT HAS ITS OWN INDIVIDUAL ARGUMENT SET THAT MAY NOT MAKE SENSE WHEN COMPARED TO OTHERS OF A SIMILAR TYPE. Such problems are evolutionary quirks and will be corrected with time.

Let's create a simple form.

Code
return &MakeComponentHTML({}, [
{
type => "formstart",
hiddens => [ # Yes, it's ugly. Sorry.
{ name => "page", value => $in{page} },
{ name => "tab", value => $in{tab} },
{ name => "d", value => "submit" },
],
},
{
type => "header",
level => 1, # 1 == blue, 2 == grey, 3/4 == alt colors
bold => 1,
title => "Example Page Header",
},
{
type => "text",
name => "test_box",
title => "Example Text Box",
desc => "Put something in the box.",
},
{
type => "formend",
submit_text => "Test the form",
},
]);
This code will be inserted into a single tab on a single page. The tab will have one blue header row ("Example Page Header"), a text box titled "Example Text Box", and a submit button saying "Test the form"

You can easily create your own component for &MakeComponentHTML, if you wish. For a type named "example", create a subroutine called &MakeComponentHTML_example. Many templates define their own components. You should model the interface for any custom components after existing components. See "selectlist" and "selectlistplustext" as examples. If you're only going to use a custom component in one template, it's safe to put the subroutine there rather than in cp2_common.

While it's good practice to use the components as much as you can, you don't really have to do so. Your template run subroutine can easily return raw HTML, or you can use the raw component type.

So, now you can put together a page, set up a form handler, and "make things go" in general.

But nothing will work unless the page can be found in the menus. Editing the menus is the last thing you'll need to know.

The menus are stored at the bottom of cp2_lib.

The menus are composed of a set of references stored in a hash. Among them are:

GENERIC_MENUS_HOMEPAGE
GENERIC_MENUS_TIER_ONE
GENERIC_MENUS_TIER_TWO
MOD_MENUS_HOMEPAGE
MOD_MENUS_TIER_ONE
MOD_MENUS_TIER_TWO
ADMIN_MENUS_HOMEPAGE
ADMIN_MENUS_TIER_ONE
ADMIN_MENUS_TIER_TWO

The generic set is loaded when there is no user logged in. The mod set is loaded when the user is a moderator. The admin set is loaded when the user is an administrator.

"homepage" is the name of the page that users receive when the breadcrumbs are used / when the user first logs in.

The first tier of menus produces the list of items on the left of the screen. It's an array reference that contains array references. The first item in any such array is the category title. All others are the names of the items in that category. For instance:

Code
$tier_one = [
["Category One", "item", "item2", "item3"],
["Cat2", "item4"],
];
The first tier menu is purely cosmetic. Valid pages may exist that are not within that menu.

The second tier menu defines each individual page and the tabs on the page.

An example page:

Code
$tier_two = {
item => {
title => "Name of Page",
hidden => 0,
nolink => 0,
menu_override => "",
extraqs => [],
tabs => [],
},
};
Only title and tabs are required. title is the actual title of the page (as will appear on the menu and in the breadcrumbs). tabs is an arrayref of the tabs on the page.

If hidden is set to 1, the menu item will not show up in the left menu, no matter what.

If nolink is set to 1, the main page will not be displayed as a breadcrumb. This can be combined with menu_override to make pages that "think" they're really somewhere else in the menu system.

If menu_override is set to a valid page name, all navigation on the page will be borrowed from that page instead. This trick is used to create stand alone tabbed pages that really belong to another page, such as the style editor and user profile editor.

extraqs contains an arrayref listing any form arguments that need to be passed into the query string when StandardHTML is called and back_button is -2. This is again part of the trickery used to make pages look like they belong somewhere else (as part of the user editor - you can't edit a user profile unless you know which profile to load).

Finally, tabs is an array reference containing the list of tabs on this page.

Code
my $tabs = [
{
id => "normal_tab",
title => "Normal Tab Title",
type => "tab",
},
{
id => "standalone_tab",
title => "Standalone Tab",
type => "standalone",
},
{
id => "anti_tab",
title => "Standalone Tab, Really!",
type => "tab",
},
{
id => "url",
title => "Click me to go somewhere...",
type => "url",
url => "http://...",
},
];
Tabs are pretty straightforward. Each tab must have three elements - the id, title, and type. The id is the name for the tab as given in URLs. The title is the name printed on the tab itself.

There are four possible tab types:

Type "tab" signifies a normal DHTML tab.

Type "standalone" is a special HTML tab. Standalone tab contents are not loaded with the other DHTML tabs. When the tab grippy is clicked, the new page loads with only that one tab. Users can click on any other DHTML or standalone tabs from any page, and will be taken to that tab, even if the page has to reload. Note that form changes will be lost during the page transition.

Type "standalonenotab" is like a standalone tab (it loads as a separate page). However, it is not a normal tab. When this tab has focus, all other tabs are hidden. This allows for multiple "pages" without needing to define real live pages.

Type "url" requires a url paramater with the tab. When the tab is clicked, the user is sent to the specified URL.

Now that I've told you all of this, it's time to make your first control panel hack!

If you haven't done so already, go grab the latest 6.6+ release (Beta Release 1 at time of writing) and install it. Let's call our new page test.

First, start with the template. Create a new file named cp2_test.pl. Put the following inside of it:

Code
# Test page template for 6.6 control panel

sub cp2_template_test_init {}
sub cp2_template_test_libs {}

sub cp2_template_test_run {
return &MakeComponentHTML([
{
type => "formstart",
hiddens => [
{ name => "page", value => "test" },
{ name => "d", value => "submit" },
],
},
{
type => "header",
level => 1,
bold => 1,
title => "Test Page Header",
},
{
type => "text",
name => "test_box",
title => "Example Text Box",
desc => "Put something in the box.",
},
{
type => "formend",
submit_text => "Test the form",
},
]);
} # end cp2_template_test_run

sub cp2_page_test {
if($in{d} eq "submit") {
&StandardHTML("Thank you. You said $in{test_box}");
} # end if

print &WrapContent(&WrapTabSet({}, [&cp2_template_test_run]));
exit;
} # end cp2_page_test

1;
Save the file and upload it to your Templates directory. Don't forget the 1 at the end!

Notice that we're cheating! The page subroutine has been put inside the template itself. If you have lots of code, you'll want to use an external library file and use the libs subroutine to load it. For such a small snippet of code, however, putting the page subroutine in the template is OK.

Now that we have the template and the page sub, we can add the test page to the menu. Open up cp2_lib.cgi and search for "ADMIN_MENUS_TIER_TWO". There will be two instances. You'll want the second one, around line 1,200.

Right below the line containing "ADMIN_MENUS_TIER_TWO", insert the following:

Code
	test => {
title => "Test Page",
tabs => [{
id => "test",
title => "Test Page",
type => "tab",
}],
},
Now, look a few lines up. You'll see a block starting with "ADMIN_MENUS_TIER_ONE" that looks something like:

Code
ADMIN_MENUS_TIER_ONE => [
[$vars_...
[$vars_...
[$vars_...
[$vars_...
[$vars_...
[$vars_...
[$vars_...
],
You'll want to add one more to the bottom, so it will look something like:

Code
	[$vars_...
[$vars_...
["Test Header", "test"],
],
Save cp2_lib.cgi, then log into the control panel as an admin. If everything went right, you should see a new heading at the bottom of the control panel menu titled "Test Header". It will contain exactly one item, "Test Page". When clicking on Test Page, you should get the test page form that we've set up, and when you submit that form, you should be told what you submitted.

If you get an internal server error or an uncaught exception, you probably made a typo. Try copying and pasting right from this document instead of typing things in by hand. Be careful not to break the first tier menus when copying and pasting. smile

If you've made it this far, congrats! You've successfully installed your first 6.6 control panel hack!

Your next challenge will be writing your own code. That should be fun. smile


UBB.classic: Love it or hate it, it was mine.
Sponsored Links
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
No one has any questions then? smile


UBB.classic: Love it or hate it, it was mine.
Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
eek that shoulda been an article too smile


- Allen wavey
- What Drives You?
Joined: Oct 2000
Posts: 2,667
Veteran
Veteran
Offline
Joined: Oct 2000
Posts: 2,667
well I have a question tipsy in cp2_general.pl I have been trying to find the code of the bottom tab in the graemlin tab. the run code is there but I can't find any &WrapTabSet or anything else that make the bottom tab appear. (if I ask this it's because I am trying to upgrade the smilie mod)

*edit*ok found it but still using an outside template couldn't figure how to integrate it in the existing template


Do you believe in love at first sight,
or should I walk by again?
Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
hmmm.. read this again, my head hurts tipsy


- Allen wavey
- What Drives You?
Sponsored Links
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
Charles: I don't understand your last question... what are you trying to do, exactly?


UBB.classic: Love it or hate it, it was mine.
Joined: Oct 2000
Posts: 2,667
Veteran
Veteran
Offline
Joined: Oct 2000
Posts: 2,667
Well I did a new template to interact with a new var file.

I wanted to add a bottom tab in the graemlin section to launch it but since it is a seperate template than the one currently loaded I was then told I was not allowed to access this template.

I then figured I had to add my routines to the general.pl template but have not found yet how I could init my var file when this specific tab was asked. My other subs are baseds on LK's calendar hack and are rather different than the way you did yours.


Do you believe in love at first sight,
or should I walk by again?
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
Are you trying to hook into an existing page or tab, or work with a new page and tab?


UBB.classic: Love it or hate it, it was mine.
Joined: Oct 2000
Posts: 2,667
Veteran
Veteran
Offline
Joined: Oct 2000
Posts: 2,667
I would like to add a bottom tab to the existing graemlin tab (that calls the new template but I then get access required problems)


Do you believe in love at first sight,
or should I walk by again?
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
So you've added the lower tab def (around line 770 of cp2_vars).... What exactly are the arguments you're passing? Does the tab show up properly? Does the link take you to the right place? Are there any error messages anywhere? I don't understand what you mean by "access required problems"....


UBB.classic: Love it or hate it, it was mine.
Sponsored Links
Joined: Oct 2000
Posts: 2,667
Veteran
Veteran
Offline
Joined: Oct 2000
Posts: 2,667
everything shows correctly but since I removed the link to the template from the left menu it is no longer in the admin list of authorised places so I cannot view the content.


Do you believe in love at first sight,
or should I walk by again?
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
Then add it back, and use the hidden attribute to prevent it from showing up.


UBB.classic: Love it or hate it, it was mine.
Joined: Jan 2003
Posts: 3,456
Likes: 2
Master Hacker
Master Hacker
Offline
Joined: Jan 2003
Posts: 3,456
Likes: 2
hey Charles, I was working on porting the hypercell hack since Gizzy gave up, and I have to create a dropdown menu for part of the hack. It would have the syntax of

Code
<select name="Cursor1">
<option value="hand" selected> select New Cursor?
<option value="hand" > Hand
<option value="text" > Text
<option value="pointer" > Pointer
<option value="wait" > Wait
<option value="help" > Help
<option value="move" > Move
<option value="n-resize" > North Resize
<option value="ne-resize" > North-East Resize
<option value="e-resize" > East Resize
<option value="se-resize" > Sout-East Resize
<option value="s-resize" > South Resize
<option value="sw-resize" > South-West Resize
<option value="w-resize" > West Resize
<option value="nw-resize" > North-West Resize
<option value="auto" > Browser Defined
<option value="default" > Computer Default
</select>
what would be the syntax to produce that?

I couldn't find anywhere in the cp where this is used, so I was just wondering. (a basic syntax for dropdown menus would be fine)

Joined: Jan 2000
Posts: 5,833
Likes: 20
UBBDev / UBBWiki Owner
Time Lord
UBBDev / UBBWiki Owner
Time Lord
Joined: Jan 2000
Posts: 5,833
Likes: 20
I didn't give up, I stated that you have exclusive rights to port any and all of my modifications... Since I have work now lol, but I will port this and that when i look into things, but in the meantime you can go crazy :x


UBB.Dev - Putting Dev into UBB.threads
Company: VNC Web Services - UBB.threads Scripts and Scripting, Install and Upgrade Services, Site and Server Maintenance.
Forums: A Gardeners Forum, Scouters World, and UGN Security
UBB.Threads: My UBB Themes, My UBB Scripts
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
Check out the selectlist component, and sub MakeForumSelectList... option lists are pretty simple.


UBB.classic: Love it or hate it, it was mine.
Joined: Jan 2003
Posts: 3,456
Likes: 2
Master Hacker
Master Hacker
Offline
Joined: Jan 2003
Posts: 3,456
Likes: 2
Quote
quote:
Originally posted by Charles Capps:
Check out the selectlist component, and sub MakeForumSelectList... option lists are pretty simple.
ok, I've looked through every file and I can't find the sub MakeForumSelectList frown

Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
It's in cp2_common.


UBB.classic: Love it or hate it, it was mine.
Joined: Jan 2003
Posts: 3,456
Likes: 2
Master Hacker
Master Hacker
Offline
Joined: Jan 2003
Posts: 3,456
Likes: 2
thanks, I found it, and I'll report back in a couple minutes once I'm confused again tipsy

Joined: Oct 2000
Posts: 2,667
Veteran
Veteran
Offline
Joined: Oct 2000
Posts: 2,667
ok got the invisible stuff, now I am trying tro define the graemlin tab as a standalone tab so that it not loaded with the rest since having to load 300 graemlins to edit general settings is a pain.

check cp2_vars but can't find where to change the tab setting to standalone


Do you believe in love at first sight,
or should I walk by again?
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
That's in the tab def... bottom of cp2_lib.


UBB.classic: Love it or hate it, it was mine.
Joined: Oct 2000
Posts: 2,667
Veteran
Veteran
Offline
Joined: Oct 2000
Posts: 2,667
danke got it smile

*edit* the add graemlin bottom tab is now gone but the code is in the same file than the graemlin tab

I still have the one I added though

designed behaviour? I need to redo the add routine anyway but I was planning to add on top of yours tipsy

*edit2* now I also get 1 error per smilie one I try to submit one of the other tag we must have a check routine somewhere, I will have to look into this.


Do you believe in love at first sight,
or should I walk by again?
Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
how's this going chuck? smile I need an example tipsy


- Allen wavey
- What Drives You?
Joined: Oct 2000
Posts: 2,667
Veteran
Veteran
Offline
Joined: Oct 2000
Posts: 2,667
just sent you the latest mhk file


Do you believe in love at first sight,
or should I walk by again?
Joined: Sep 2003
Posts: 6
Junior Member
Junior Member
Offline
Joined: Sep 2003
Posts: 6
How can I run Javascript code when the user clicks on a tab, not when the page is loaded?

Joined: Jul 2003
Posts: 273
Member
Member
Offline
Joined: Jul 2003
Posts: 273
set the script to run onMouseClick rather than onLoad .

Joined: Jul 2003
Posts: 273
Member
Member
Offline
Joined: Jul 2003
Posts: 273
then again I don't know this stuff so I just took a stab at it. Someone correct me if I'm wrong... which is likely.

Joined: Sep 2003
Posts: 6
Junior Member
Junior Member
Offline
Joined: Sep 2003
Posts: 6
The tab code is generated by UBB.Classic itself. I need to know where and how to set the OnClick property (in cp2_lib.cgi or somewhere else)

Joined: Jul 2003
Posts: 273
Member
Member
Offline
Joined: Jul 2003
Posts: 273
I told you I didn't know what I was talking about. smile

I'm reading up on it all now though so I should be able to eventually answer questions with some accuracy. Until then I'll shut up. smile

Joined: Jun 2001
Posts: 2,849
Spotlight Winner
Spotlight Winner
Offline
Joined: Jun 2001
Posts: 2,849
I'm nothing but confused by this thread but I have a function that I really need. The old backup hack was awesome and I've been looking for a way to leverage it but this single line of code from the old CP has me stumped as to how I can add it to the new CP *easily*.

Code
document.writeln("<option value=$vars_config{CGIURL}/cp.cgi?ubb=backup&r=$ran> - Backup your UBB</option>");
I realize that easily was not the best choice of terms but I'm not a programmer, just a brave user.

Edit: I've looked further into it an apparently there is a LOT more to it than that. *sigh* I hate being code crippled.

Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
You need to add an item to the menu. Read the first post again about how items in the menu get added...


UBB.classic: Love it or hate it, it was mine.
Joined: Jun 2001
Posts: 2,849
Spotlight Winner
Spotlight Winner
Offline
Joined: Jun 2001
Posts: 2,849
Quote
quote:
Originally posted by Charles Capps:
You need to add an item to the menu. Read the first post again about how items in the menu get added...
Thanks, I'll do that.

Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
first attempt at this new cp hacking, can you glance at this and tell me if there's something glaringly wrong tipsy

https://www.ubbdev.com/ubb/upload/00000494/cp2_backup.txt

There's probably some html whackiness in the second sub printed, but that should be simple to correct smile


- Allen wavey
- What Drives You?
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
The code looks fine, other than a lact of strict. smile

You should be using type => header (bold => 0, level => 3 or 4) instead of injecting HTML using type => raw.

d => submit is usually used only in two-action forms (i.e. view, then submit). In multi-part forms like this seems to be, d should be equal to whatever part of the form needs to be run. However, you might not even need to do that, if you have different subs for each tab instead...

Then again, I might be totally off base, having not seen the main code.


UBB.classic: Love it or hate it, it was mine.
Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
hehe, ok, thank you Charles smile I'm at least headed in the right direction. I was mistaking the type => header for an actual header code like (tdheader). It's basically a new row of html smile


I'll work a bit more on it and then post the main code and the template file shortly... I've just begun converting it from the 6.3 series version and it's got a ways to go yet smile


- Allen wavey
- What Drives You?
Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
oh, and there's a different sub for each tab smile


- Allen wavey
- What Drives You?
Joined: Jun 2001
Posts: 2,849
Spotlight Winner
Spotlight Winner
Offline
Joined: Jun 2001
Posts: 2,849
Awesome job so far AA.

Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
installed on a test site, found/fixed a lotta small errors, but I think I'm missing something obvious to everyone but me tipsy

When I click on the link in the cp, I get this:

"Backup
The page and/or tab you requested is unavailable. The required code could not be properly loaded. Please ensure that all scripts, libraries, and templates have been properly uploaded. "

The url includes: /cp.cgi?page=backup

Anyways, here's what I've got so far:

https://www.ubbdev.com/ubb/upload/00000494/ubb_backup.zip

Don't laugh too much, but if someone wants to take a look and see what I've missed to start with so I can get back to getting errors to work out tipsy


- Allen wavey
- What Drives You?
Joined: Jan 2000
Posts: 5,073
Admin Emeritus
Admin Emeritus
Joined: Jan 2000
Posts: 5,073
You're calling in cp2_vars in the template, but not cp2_backup itself. Remember, the template is loaded first, then it dictates what libraries it needs to be run...


UBB.classic: Love it or hate it, it was mine.
Joined: Jun 2001
Posts: 2,849
Spotlight Winner
Spotlight Winner
Offline
Joined: Jun 2001
Posts: 2,849
The original hack only used the one page for deciding which backup you got, either members, cgi-bin, noncgi or a custom path set in the vars_wordlets_mods file. The four functions were done automatically so you didn't select them as you would tabs.

Once you chose the files to be backed up the rest was automatic and the last thing you'd do would be to click on the "delete backup" button to remove it (the backup file) from the noncgi folder. I think the page should be a single tab with just the radio buttons and the rest is handled by the cp2_backup.cgi file.

Joined: Mar 2000
Posts: 21,079
Likes: 3
I type Like navaho
I type Like navaho
Joined: Mar 2000
Posts: 21,079
Likes: 3
Thanks Charles, I added a call to cp2_backup but am getting the same error message. smile

Randy, each sub in the original had a submit in it, it still refreshed with one page?


- Allen wavey
- What Drives You?
Page 1 of 2 1 2

Link Copied to Clipboard
Donate Today!
Donate via PayPal

Donate to UBBDev today to help aid in Operational, Server and Script Maintenance, and Development costs.

Please also see our parent organization VNC Web Services if you're in the need of a new UBB.threads Install or Upgrade, Site/Server Migrations, or Security and Coding Services.
Recommended Hosts
We have personally worked with and recommend the following Web Hosts:
Stable Host
bluehost
InterServer
Visit us on Facebook
Member Spotlight
Nettomo
Nettomo
Germany, Bremen
Posts: 417
Joined: November 2001
Forum Statistics
Forums63
Topics37,573
Posts293,925
Members13,849
Most Online5,166
Sep 15th, 2019
Today's Statistics
Currently Online
Topics Created
Posts Made
Users Online
Birthdays
Top Posters
AllenAyres 21,079
JoshPet 10,369
LK 7,394
Lord Dexter 6,708
Gizmo 5,833
Greg Hard 4,625
Top Posters(30 Days)
Top Likes Received
isaac 82
Gizmo 20
Brett 7
WebGuy 2
Morgan 2
Top Likes Received (30 Days)
None yet
The UBB.Developers Network (UBB.Dev/Threads.Dev) is ©2000-2024 VNC Web Services

 
Powered by UBB.threads™ PHP Forum Software 8.0.0
(Preview build 20221218)