I just thought I'd start a thread for all my questions, instead of multiple threads for each problem or question.

Anyways, here goes:

I'm trying to render a form that gets a value from an external php.

In detail:

I'm creating a user calendar module that allows users to create their own calendars and add their own events. However, I'm using an ajax calendar that has it's own .js and .php. The php file is what actually displays the calendar and the .js handles all the ajax.

When a user clicks on an icon on a specific date, it should pass a value of what that date is back to the module file.

Unfortunately I can't reference to anything as my company is doing development on a virtual private server and no one would be able to see it anyway.

Thanks for any suggestions.

Comments

CWolff’s picture

Here's what the code looks like:

.module file:

function usercalendar_createevent(){
	$form['calendareventcreate']['eventname'] = array('#type' => 'textfield',
      '#title' => t('Event Name'),
      '#description' => t('Title of your event.'),
	  '#size' => 40,
      );
	  $form['calendareventcreate']['eventdescription'] = array('#type' => 'textarea',
	  '#title' => t('Event Description'),
	  '#description' => t('Enter the details of your event'),
	  );
	  $form['calendareventcreate']['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Create Event')
    );
	return $form;
}

function usercalendar_createevent_submit($form_id, $form_values){
	$query = mysql_query("INSERT INTO user_calendar (event_desc) VALUES('Hello!') ") or die(mysql_error());  
}

the .js file (that gets called from the .module via drupal_add_js)

function navigate(month,year,activity) {
		var url = "modules/usercalendar/calendar.php?month="+month+"&year="+year+"&activity="+activity;
        if(window.XMLHttpRequest) {
                req = new XMLHttpRequest();
        } else if(window.ActiveXObject) {
                req = new ActiveXObject("Microsoft.XMLHTTP");
        }
        req.open("GET", url, true);
        req.onreadystatechange = callback;
        req.send(null);
}

the .php calendar that actually displays it is nothing more than html in an echo.

Now, I'm trying to get it so that when someone clicks on a date in the .php file, a variable (of the epoch date of the day they clicked) will get sent back to the .module file somehow so I can include it in my INSERT statement.

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

nevets’s picture

Are you trying to implement a date picker or is it more than that?

CWolff’s picture

Yeah, it's a date picker in epoch form, I was having trouble passing a variable from the external php file back to the module file, but I think I figured it out.

I did this:

in the calendar external php file:

$timestamp = mktime(0, 0, 0, $mnumber, $cur, $year2);

		$output.="><div class=\"dayedit\"><span class=\"left\"><a href= \"?q=tools/mycalendar/create/".$timestamp."\"><img src=\"themes/ability/img/calendar-add.gif\" /></a></span><span class=\"right\"><a href=\"\"><img src=\"themes/ability/img/calendar-edit.gif\" /></a></span></div>

So that when you clicked on the image link, it would go to the form as defined the module file, but with an additional /url in it, like: ?q=tools/mycalendar/create/1196060400 where the epoch date after create is the argument.

And then I did this in the module file:

function usercalendar_createevent(){
	
	// Get POST variable from the calendar date
	$timestamp = arg(3);
	$form['calendareventcreate']['eventname'] = array('#type' => 'textfield',
      '#title' => ('Event Name'),
      '#description' => ('Title of your event.'),
	  '#size' => 40,
      );
	  $form['calendareventcreate']['eventdescription'] = array('#type' => 'textarea',
	  '#title' => ('Event Description'),
	  '#description' => ('Enter the details of your event'),
	  );
	  $form['calendareventcreate']['submit'] = array(
      '#type' => 'submit',
      '#value' => ('Create Event'),
      );
	  $form['calendareventcreate']['timestamp'] = array(
      '#type' => 'hidden',
      '#value' => $timestamp,
      );
	return $form;
} // end user_calendar_createevent

and used the arg(3) to retrieve the epoch date.

Now I can just call it from the _submit function and insert it, right?

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

nevets’s picture

As far as I can tell from what you have shown it should work.

CWolff’s picture

It worked just fine.

but on a related note: is it possible to render the form on the page defined in the menu hook, but WITHOUT surrounding drupal content.

For instance: I'm trying to render this drupal form in an ajax popup window, so, logically, I JUST need the form, however, when I implement the popup window, it displays the site in the little popup. How can I render JUST the form?

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

nevets’s picture

The simple part is you need to change how the form is invoked so you have more control. The menu item form mycalendar would be changed to

  $items[] = array(
    'path' => 'mycalendar',
    'title' => t('Create a New Calendar'),
    'callback' => 'usercalendar_getform',
    'access' => user_access('create calendar'),
    'type' => MENU_CALLBACK
  );

and you would add the function

function usercalendar_getform() {
  print drupal_get_form('usercalendar_createpage');
}

The use of the print statement (vs the "normal" return means that the theming will be bypassed) and you end up with just the form.

The above answers you question literally but ignores some issues. The first being it assumes you never need the form in a themed page. In addition it ignores how the form becomes a popup, how the form submittion is handled and how errors are dealt with. For handling the form as a popup I like the jqModal jQuery plugin, For form submittion I like jquery.form.js, (there are other choices for both). In addition when you build the form you will need to set $form['#action'] to the path (I believe 'mycalendar' would be the correct path for this). Note the recommend plugins will only handle basic forms and will not handle file or image uploads. As for error handling that is a challange and I do not have a neat solution for it.

CWolff’s picture

Okay that worked....however, I'm not so pleased with it, it would be pretty illogical to have to include separate stylings...

Having created a popup from the <a href>...would it be possible for that <a> tag to call a function within the module?

For example:

<a href = "usercalendar.module?action=blah"></a>
and have it return the content within whatever function "Blah" points to in the module?

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

nevets’s picture

That's what the menu hooks are all about, they allow you to define paths and the associated callback.

Using the menu item for 'mycalendar' and my modified code the basics of adding arguments to a callback follow this pattern,
mycalander/arg1/arg2 where arg1 and arg2 become arguments to the callback function. Using your question as an example the link might read <a href =mycalander/popup"></a> and the callback like

function usercalendar_getform($action = '') {
  $output = drupal_get_form('usercalendar_createpage');
  if ( $action == 'popup' ) {
    print $output;
  }
  else {
    return $output;
  }
}

Note you could also define two menu callbacks both of which call drupal_get_form() using the same form with one using 'priint' and the other 'return'.
Also note that handling errors when the form can be either a popup or regular form gets more complicated.

CWolff’s picture

Hmmm....it does work to an extent...but I'm also trying to incorporate a javascript action within the output, so that if $action =='popup' it will execute a query and then automatically close the window...so I tried:

function usercalendar_getform($action = '') {
  $output = drupal_get_form('usercalendar_createpage');
  if ( $action == 'popup' ) {
    $query = mysql_query("INSERT whatever INTO whatever");
    $output .= "<script>window.close();</script>";
    print $output;
  }
  else {
    return $output;
  }
}

But I either get a "Page Cannot Be Displayed" or a "Cannot Modify Header Information" Error.
------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

nevets’s picture

Given the context of what you doing you question does not make sense to me.

The function usercalendar_getform() is used to display the form, not process the form so the the query does not make sense (side note, you should be using db_query and not mysql_query). The second part

    $output .= "<script>window.close();</script>";

is probably not going to do what you expect. Since it is inline javascript it should try and close the window then and there. You really need a submit handler tied to the form that closes the window when the user submits the information.

CWolff’s picture

I have an array of dynamic checkboxes for a form to be rendered like so:


function render_product_options(){
	$output =array();
	$query = mysql_query("SELECT * FROM term_data WHERE vid = '8'");
	while ($row = mysql_fetch_array($query)){
		$output[] = $row['name'];
	}
	return $output;
} // end render_product_options

however, when I call it in the $form element like this:


$form['products'] = array('#type' => 'checkboxes', '#tree' => TRUE, '#title' => t('Select the products you own'), '#options' => render_product_options());

the very first checkbox has an index of 0, so I can't tell if it's been checked or not, help?
------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

nevets’s picture

Change

 $output[] = $row['name'];

to

 $output[$row['tid']] = $row['name'];

That way the options are indexed by tid, never zero and you can tell which term was checked.

CWolff’s picture

Doesn't that interfere with my ability to call a loop to retrieve the results?

$array = $form_values['products'];
$p = 0;
	while ($p < $numtotal){
		echo $array[$p];
		$p++;
	}

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

CWolff’s picture

Answered my own question with array_keys :)

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

nevets’s picture

You can also use a foreach loop like this

foreach ( (array) $form_values['products'] as $tid => $value ) {
  // Do something with $tid and/or $value
}
CWolff’s picture

What file could I include to make a connection to the drupal database from an external file? (i.e. not a file read by the drupal framework)

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

CWolff’s picture

I try:

include($_SERVER['DOCUMENT_ROOT']."/sites/default/settings.php");
include($_SERVER['DOCUMENT_ROOT']."/includes/database.mysql.inc");

However, it tells me that access is denied, and the username and password is different from what I have in the settings.php file.

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com

CWolff’s picture

Also, within a drupal form, is it possible to have a confirmation before submitting a form?

I had something similar to:

onclick attribute in drupal form (delete button)

calls to js function that does a:

if(confirm("Blah"))

form.submit

but, it seems that either both the "OK" and "Cancel" buttons either don't do anything, or they both submit the form....

------------------------
Cassandra Wolff
PHP Developer
Gaiam Inc.
Direct: 303-222-3676
cassandra.wolff@gaiam.com