*/
public function __construct(PDO $pdo, $month, $year)
{
- $this->dbh = $pdo;
- $this->_month = ctype_digit($month) ? $month: date('n');
- $this->_year = ctype_digit($year) ? $year: date('Y');
+ $this->dbh = $pdo;
+ $this->_month = filter_var($month, FILTER_VALIDATE_INT) ? $month: date('n');
+ $this->_year = filter_var($year, FILTER_VALIDATE_INT) ? $year: date('Y');
+ $this->baseURL = MEDIA_BASE_URL;
}
// }}}
// {{{ getEventsForMonth()
$this->_year
)
);
- // $sDates will be our $this->_selectedDays array;
- $sDates = array();
- // get all event for this month only
- $sql = "
- SELECT id,bdate,edate,daysow,dayom,reacur,weekom
- FROM event
- WHERE bdate <= :end
- AND edate >= :begin
- AND visable = 't'
- ORDER BY bdate,edate";
-
- try {
- $stmt = $this->dbh->prepare($sql);
- $stmt->bindParam(":begin", $begin, PDO::PARAM_STR);
- $stmt->bindParam(":end", $end, PDO::PARAM_STR);
- $stmt->execute();
- while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- // timestamp of events starting date
- $bdate = strtotime($row['bdate']);
- // timestamp of events ending date
- $edate = strtotime($row['edate']);
- // if the dates are the same then add it to the
- // selected dates array
- if ($bdate == $edate) {
- $sDates[] = new Calendar_Day(
- date('Y', $bdate),
- date('n', $bdate),
- date('d', $bdate)
- );
- } else if ($edate > $bdate) {
- // if the end date is larger than the starting one
- // only work in this month
- // timestamp for start of month
- $startOfMonth = mktime(
- 0,
- 0,
- 1,
- $this->_month,
- 1,
- $this->_year
- );
- // timestamp for end of month
- $endOfMonth = mktime(
- 0,
- 0,
- 1,
- $this->_month,
- date('t', $startOfMonth),
- $this->_year
- );
- // update the start date if needed
- if ($startOfMonth >= $bdate) {
- $bdate = $startOfMonth;
- }
- // update the end date if needed
- if ($endOfMonth <= $edate) {
- $edate = $endOfMonth;
- }
- // find events ord
- if ($row['weekom']) {
- if ($row['daysow']) {
- $ri = 1;
- for ($r = 0; $r < 7; $r++) {
- if ($row['daysow'] & $ri) {
- $ord[] = $this->ordinalDay(
- $row['weekom'],
- $r,
- $this->_month,
- $this->_year
- );
- }
- $ri = $ri << 1;
- }
- } else {
- $ord = null;
- }
- } else {
- $ord = null;
- }
- // seconds in one day = 86400
- // loop through the days in this month
- for ($i = $bdate; $i <= $edate; $i = $i + 86400) {
- $cur_dow = date("w", $i);
- switch($cur_dow) {
- case 0:
- $cur_dow = 1;
- break;
- case 1:
- $cur_dow = 2;
- break;
- case 2:
- $cur_dow = 4;
- break;
- case 3:
- $cur_dow = 8;
- break;
- case 4:
- $cur_dow = 16;
- break;
- case 5:
- $cur_dow = 32;
- break;
- case 6:
- $cur_dow = 64;
- break;
- }
- // if the event is not a recurring one then add it as
- // selectedDay
- if (!$row['reacur']) {
- $sDates[] = new Calendar_Day(
- date('Y', $i),
- date('n', $i),
- date('d', $i)
- );
- } else if ($row['reacur']
- && !$row['dayom']
- && $row['daysow']
- && (int)$cur_dow & $row['daysow']
- ) {
- // if the event is recurring and the daysow are set
- if ($row['weekom'] == 9) {
- // every other week
- unset($eWeeks);
- $fWeekNum = date("W", $bdate);
- if (date('w', $bdate) == 0) {
- $fWeekNum++;
- }
- $lWeekNum = date("W", $edate);
- if (date('w', $edate) == 0) {
- $lWeekNum++;
- }
- for ($fi = $fWeekNum;
- $fi <= $lWeekNum;
- $fi = $fi + 2
- ) {
- $eWeeks[] = $fi;
- }
- $cDateWeek = date("W", $i);
- if (date('w', $i) == 0) {
- $cDateWeek++;
- }
- if (in_array($cDateWeek, $eWeeks)) {
- $sDates[] = new Calendar_Day(
- date('Y', $i),
- date('n', $i),
- date('d', $i)
- );
- }
- } else if ($row['weekom'] && is_array($ord)) {
- // if the ord is set (every 1st 2nd 3rd etc.)
- foreach ($ord as $ordinal) {
- if (date('m-d-Y', $i) == date('m-d-Y', $ordinal)) {
- $sDates[] = new Calendar_Day(
- date('Y', $i),
- date('n', $i),
- date('d', $i)
- );
- }
- }
- } else if (!$row['weekom']
- && (int)$cur_dow & $row['daysow']
- ) {
- // if daysow is set but not weekom
- $sDates[] = new Calendar_Day(
- date('Y', $i),
- date('n', $i),
- date('d', $i)
- );
- }
- } else if ($row['reacur'] && $row['dayom']
- && (int)$row['dayom'] == (int)date('j', $i)
- ) {
- // if the dayom is set
- $sDates[] = new Calendar_Day(
- date('Y', $i),
- date('n', $i),
- date('d', $i)
- );
- }
- }
- }
- }
- $this->_selectedDays = $sDates;
- } catch(PDOException $e) {
- die($e->getMessage());
+ if (!defined('COMMON_EVENTS_SCHEMA')) {
+ define('COMMON_EVENTS_SCHEMA', 'events');
}
- }
- // }}}
- // {{{ ordinalDay(
- /**
- * ordinalDay
- * get ordinal (th) day for given timestamp
- *
- * @param int $ord 1-5 1st 2nd 3rd (etc.)
- * @param int $day day
- * @param int $month month
- * @param int $year year
- *
- * @access public
- * @return int
- */
- function ordinalDay($ord, $day, $month, $year)
- {
- $firstOfMonth = mktime(
- 0,
- 0,
- 1,
- $month,
- $day,
- $year
- );
- $lastOfMonth = mktime(
- 0,
- 0,
- 1,
- $month,
- date("t", $firstOfMonth),
- $year
- );
- $dayOccurs = 0;
+ if (!defined('COMMON_APP_BASE')) {
+ define('COMMON_APP_BASE', '/var/www/server/CommonApps/');
+ }
+ require_once COMMON_APP_BASE . 'EventCalendar/V1/models/EventMapper.php';
+ $eventMapper = new EventMapper(Toolkit_Database::getInstance());
- for ($i = $firstOfMonth; $i < $lastOfMonth ; $i += 86400) {
- if (date("w", $i) == $day) {
- $dayOccurs++;
- if ($dayOccurs == $ord) {
- $ordDay = $i;
- }
+ $events = $eventMapper->fetchFilteredEventsFromTimes(
+ "et.ending >= '{$begin}' AND et.starting <= '{$end}'",
+ null,
+ false,
+ false
+ );
+ $this->_selectedDays = array();
+ foreach ($events as $event) {
+ //echo '<pre>'.print_r($events, true).'</pre>';
+ if(preg_match('%([0-9]{2})/([0-9]{2})/([0-9]{4})%', $event->getStarting(), $dateParts)) {
+ //echo '<pre>'.print_r($dateParts, true).'</pre>';
+ $this->_selectedDays[] = new Calendar_Day(
+ $dateParts[3],
+ $dateParts[1],
+ $dateParts[2]
+ );
}
}
- return $ordDay;
+ //echo '<pre>'.print_r($this->_selectedDays, true).'</pre>';
+ //echo '<pre>'.print_r($events, true).'</pre>';
+ //exit;
}
// }}}
// {{{ toHtml()
{
$GLOBALS['bottomScripts'][]
= $this->baseURL . 'Toolkit/Events/libjs/calendar.js';
- $linkPage = MEDIA_BASE_URL . 'index.php?';
+ $linkPage = BASE_URL . 'index.php?';
$page = $linkPage;
- $page .= 'catid=' . EVENT_PAGE . '&flat=1&';
+ $page .= 'catid=' . EVENT_PAGE . '&';
// create the class array with events
$this->getEventsForMonth();
+ //var_dump($this->_selectedDays);exit;
// create the calendar_month_weekdays object
$Month = new Calendar_Month_Weekdays(
$this->_year, // year
$out = "<div id=\"eventCalendar\"><table>\n";
if ($this->showPrevNextLinks) {
- $prevLink = '<a class="calLink" rel="'.$monthUri->prev('month').'" href="' . $linkPage
- . $monthUri->prev('month')
- . '"><<</a>';
+ $currentCalendar
+ = ($Month->thisMonth() == date('n') && $Month->thisYear() == date('Y'))
+ ? true
+ : false;
+ if (!$currentCalendar) {
+ $prevLink = '<a class="calLink" rel="'.$monthUri->prev('month').'" href="' . $linkPage
+ . $monthUri->prev('month')
+ . '"><<</a>';
+ } else {
+ $prevLink = ' ';
+ }
$nextLink = '<a class="calLink" rel="'.$monthUri->next('month').'" href="' . $linkPage
. $monthUri->next('month')
. '">>></a>';
}
$out .= '<tr>
<th>' . $prevLink . '</th>
- <th colspan="5">'
+ <th class="monthname" colspan="5">'
. $monthText->thisMonthName()
. ' '
. $Month->thisYear()
}
// }}}
}
-?>
--- /dev/null
+<?php
+
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * New Event Form
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Events
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AddEventForm.php,v 1.20 2010/07/04 23:58:22 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * New Event Form
+ *
+ * @category Toolkit
+ * @package Events
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Events_AddCommonEventForm
+ extends Toolkit_FormBuilder
+ implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * Table in Database which holds the contact data
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'events.events';
+
+ /**
+ * Table meta data
+ *
+ * This is used when inserting/updating data for the records
+ * so the PDO's can use explicit data types for the parameters.
+ *
+ * @var array
+ * @access public
+ */
+ public $tableMetaData;
+
+ /**
+ * Who to send the email to when the contact form is submitted
+ *
+ * If you leave this blank, its value will get set to the OWNER_EMAIL
+ * in the constructor.
+ *
+ * If you ***DO NOT*** want any emails to go out when the form is submitted
+ * then set the value to false. Do not set it to 0 for false, because the
+ * check uses a strict type check to determine if the value is actually
+ * false. This is what allows for the empty value as an option, which sets
+ * the value to OWNER_EMAIL and won't override the $email property if
+ * this class gets subclassed and the value for this property gets set in
+ * the properties of the subclass and not in the constructor after this
+ * constructor function is called.
+ *
+ * tongue twister...I know.
+ * <code>
+ * protected $email = false;
+ * </code>
+ *
+ * @var unknown
+ * @access protected
+ */
+ protected $email;
+
+ /**
+ * From header in the owner email
+ *
+ * This just sets the From header in the owner email
+ * SITENAME <from@email.com>
+ *
+ * It gets set to the constant SITENAME in the constructor if you leave
+ * empty here, but you can set it to something different here to override
+ * that if you desire.
+ *
+ * @var unknown
+ * @access protected
+ */
+ protected $siteName;
+
+ /**
+ * Email subject and <h1> header in email
+ *
+ * It gets set in the constructor if you leave empty here, but you
+ * can set it to something different here to override that if you desire.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $subject = 'New Event Submission';
+
+ /**
+ * Message to display if the form is successfully submitted
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+ <style type="text/css">
+ #category {display:none};
+ .listings {display:none};
+ </style>
+ <div id="form-sucess-top">
+ Your event has been successfully added to the events calendar,
+ however will not be visible until it has been approved by
+ the Web site administrator. Thank You.
+ </div>';
+
+ /**
+ * Extra rules for processesing
+ *
+ * This registers the Zip validation rules (and any others listed) for
+ * QuickForm.
+ *
+ * Zip validation checks both US and Canadian Zip codes
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array(
+ 'phone',
+ array(
+ 'checkEmail',
+ 'callback',
+ 'email',
+ 'Validate'
+ ),
+ array(
+ 'checkURI',
+ 'callback',
+ 'uri',
+ 'Validate'
+ )
+ );
+
+ /**
+ * Options for flexy templating engine
+ *
+ * Pulls the preset options from the setup.phtml file
+ * overwrites the templateDir and compileDir to match this classes needs
+ *
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions;
+
+ protected $eventMapper;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object
+ * @param string $formName Form's name.
+ * @param string $method (optional)Form's method defaults to 'POST'
+ * @param string $action (optional)Form's action
+ * @param string $target (optional)Form's target defaults to '_self'
+ * @param mixed $attributes (optional)Extra attributes for <form> tag
+ * @param bool $trackSubmit (optional)Whether to track if the form was
+ * submitted by adding a special hidden field
+ *
+ * @access public
+ */
+ public function __construct(
+ PDO $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false,
+ EventMapper $eventMapper
+ ) {
+ parent::__construct(
+ $formName, $method, $action, $target, $attributes, $trackSubmit
+ );
+
+ $this->dbh = $pdo;
+ $this->eventMapper = $eventMapper;
+
+ if ($this->email !== false && empty($this->email)) {
+ // Set to false to turn off email function.
+ $this->email = ADD_EVENT_EMAIL;
+ }
+ if (empty($this->siteName)) {
+ $this->siteName = SITENAME;
+ }
+ if (empty($this->subject)) {
+ $this->subject = 'Contact Request from website ' . SITENAME;
+ }
+
+ $this->flexyOptions = $GLOBALS['flexyOptions'];
+ $this->flexyOptions['templateDir'] = dirname(__FILE__) . "/templates/";
+ $this->flexyOptions['compileDir'] = dirname(__FILE__) . "/templates/compiled/";
+
+ $var = basename(__FILE__, '.php');
+
+ $callbackUrl = MEDIA_BASE_URL;
+
+ $this->captchaOptions = array(
+ 'width' => 100,
+ 'height' => 50,
+ 'callback' => "{$callbackUrl}Toolkit/qfcaptcha.php?var=$var",
+ 'sessionVar' => $var,
+ 'imageOptions' => array(
+ 'font_size' => 16,
+ 'font_path' => GLM_APP_BASE . 'glmPEAR/Image/Canvas/Fonts/',
+ 'font_file' => 'times.ttf',
+ 'background_color' => '#cccccc',
+ 'obfuscation' => false,
+ 'angle' => true,
+ ),
+ );
+ }
+
+ // }}}
+ // {{{ checkDate()
+
+ /**
+ * Validate date input
+ *
+ * allows for empty dates to be valid
+ *
+ * @param array $date date group from form
+ *
+ * @return boolean true if valid, false if not
+ * @access public
+ */
+ public function checkDate($date)
+ {
+ if (!$date) {
+ return true;
+ } else {
+ return Validate::date($date, array('format' => '%m/%d/%Y'));
+ }
+ }
+
+ // }}}
+ // {{{ checkDateRange()
+
+ /**
+ * Validate date input
+ *
+ * allows for empty end date to be valid
+ *
+ * @param array $d date group from form
+ *
+ * @return boolean true if valid, false if not
+ * @access public
+ */
+ public function checkDateRange(array $d)
+ {
+ if (!$this->hasEndDate($d[1])) {
+ // no end date is a valid date range
+ return true;
+ }
+ $pattern = '/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/';
+ if (preg_match($pattern, $d[0], $m)) {
+ $t1 = mktime(0, 0, 0, (int) $m[1], (int) $m[2], (int) $m[3]);
+ $bdate = new Date($t1);
+ }
+ if (preg_match($pattern, $d[1], $m)) {
+ $t2 = mktime(0, 0, 0, (int) $m[1], (int) $m[2], (int) $m[3]);
+ $edate = new Date($t2);
+ }
+ if ($bdate && $edate) {
+ // 0 if the dates are equal - valid
+ // -1 if $bdate is before $edate - valid
+ // 1 if $bdate is after $edate - invalid
+ $res = Date::compare($bdate, $edate);
+ return ($res !== 1);
+ }
+ return true;
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Form element definitions
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'header',
+ 'name' => 'eventInfoHdr',
+ 'display' => 'Event Information'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'header',
+ 'display' => 'Event Name'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'starting',
+ 'display' => 'Start Date',
+ 'opts' => array('id' => 'sdate')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'ending',
+ 'display' => 'End Date',
+ 'opts' => array('id' => 'edate')
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => false,
+ 'name' => 'btime',
+ 'display' => 'Start Time',
+ 'opts' => array(
+ 'format' => 'h : i A',
+ 'addEmptyOption' => true,
+ 'emptyOptionValue' => '',
+ 'emptyOptionText' => array(
+ 'h' => 'hh',
+ 'i' => 'mm',
+ 'A' => 'am/pm'
+ ),
+ 'optionIncrement' => array(
+ 'i' => 15,
+ ),
+ ),
+ 'error' => 'ERROR: You must select a start time!',
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => false,
+ 'name' => 'etime',
+ 'display' => 'End Time',
+ 'opts' => array(
+ 'format' => 'h : i A',
+ 'addEmptyOption' => true,
+ 'emptyOptionValue' => '',
+ 'emptyOptionText' => array(
+ 'h' => 'hh',
+ 'i' => 'mm',
+ 'A' => 'am/pm'
+ ),
+ 'optionIncrement' => array(
+ 'i' => 15,
+ ),
+ ),
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => true,
+ 'name' => 'category',
+ 'display' => 'Category',
+ 'opts' => $this->getTopicFields(),
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'website',
+ 'display' => 'Event Website'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'facebook',
+ 'display' => 'Facebook',
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'twitter',
+ 'display' => 'Twitter',
+ );
+
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'cost',
+ 'display' => 'Cost',
+ );
+
+ $e[] = array(
+ 'type' => 'textarea',
+ 'req' => false,
+ 'name' => 'description',
+ 'display' => 'Event Description',
+ 'opts' => array('id' => 'description')
+ );
+ $e[] = array(
+ 'type' => 'header',
+ 'name' => 'eventLocationInfoHeader_rmv',
+ 'display' => 'Event Location Information
+ <div id="map-dialog">
+ <div id="map_canvas" style="width:500px; height:400px"></div>
+ </div>
+ <a id="map-it" href="#">Map It</a>'
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'lat',
+ 'opts' => array('id' => 'lat')
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'lon',
+ 'opts' => array('id' => 'lon')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'place',
+ 'display' => 'Place'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'address',
+ 'display' => 'Address'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'city',
+ 'display' => 'City'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'state',
+ 'display' => 'State'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'zip',
+ 'display' => 'ZIP'
+ );
+ $e[] = array(
+ 'type' => 'header',
+ 'name' => 'eventContactHeader_rmv',
+ 'display' => 'Event Contact Information'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'contact_name',
+ 'display' => 'Event Contact Person<br>(published on Web site)'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'contact_email',
+ 'display' => 'Contact Email<br>(published on Web site)'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'contact_phone',
+ 'display' => 'Contact Phone<br>(published on Web site)'
+ );
+
+ $e[] = array(
+ 'type' => 'header',
+ 'name' => 'adminInfoHdr',
+ 'display' => 'Event Admin Information'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'admin_contact',
+ 'display' => 'Contact Name Submitting Event'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'admin_org',
+ 'display' => 'Organization Name Submitting Event'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'admin_phone',
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'admin_email',
+ 'display' => 'Email Address'
+ );
+
+ if ($this->useCaptcha) {
+ $e[] = array(
+ 'type' => 'CAPTCHA_Image',
+ 'req' => false,
+ 'name' => 'captcha_question',
+ 'display' => 'Verification code',
+ 'opts' => $this->captchaOptions
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'captcha_rmv',
+ 'display' => 'Enter verification code',
+ );
+ }
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit_rmv',
+ 'display' => 'Submit'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Form filter definitions
+ *
+ * Applies a data filter for the given fields when the form is submitted
+ *
+ * @return void
+ * @access public
+ */
+ public function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+ $f[] = array(
+ 'element' => 'website',
+ 'filter' => array('Toolkit_Common', 'filterURI')
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper function to handle setting up the form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Form rule definitions
+ *
+ * Adds validation rules for the given fields
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ // Form Rules
+ $r[] = array(
+ 'element' => 'topicid',
+ 'message' => 'ERROR: Invalid Category!',
+ 'type' => 'numeric',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'email',
+ 'message' => 'ERROR: Invalid Email Format!',
+ 'type' => 'checkEmail',
+ 'format' => array('use_rfc822' => true),
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => array('starting', 'ending'),
+ 'message' => 'ERROR: Starting Date must be before Ending Date',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkDateRange'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'starting',
+ 'message' => 'ERROR: Invalid date!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkDate'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'ending',
+ 'message' => 'ERROR: Invalid date!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkDate'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'website',
+ 'message' => 'ERROR: Invalid URL format',
+ 'type' => 'checkURI',
+ 'format' => array(
+ 'allowed_schemes' => array('http', 'https'),
+ 'strict' => false
+ ),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'contact_phone',
+ 'message' => 'ERROR: Invalid Phone Format (xxx) xxx - xxxx!',
+ 'type' => 'phone',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ if ($this->useCaptcha) {
+ $r[] = array(
+ 'element' => 'captcha_rmv',
+ 'message' => 'ERROR: What you entered didn\'t match!',
+ 'type' => 'CAPTCHA',
+ 'format' => $this->captchaQuestion,
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ }
+
+ $this->setupRules($r);
+ }
+
+ // }}}
+ // {{{ getTopicFields()
+
+ /**
+ * get event topics
+ *
+ * @return array topics
+ * @access protected
+ */
+ protected function getTopicFields()
+ {
+ $categories = array('' => '- select -');
+ $catData = $this->eventMapper->fetchAllCategories();
+ foreach ($catData as $category) {
+ $categories[$category->getId()] = $category->getName();
+ }
+ return $categories;
+ }
+
+ // }}}
+ // {{{ hasEndDate()
+
+ /**
+ * verifies if we have a valid end date to work with
+ *
+ * @param array $d end date
+ *
+ * @return boolean if the end date is
+ */
+ protected function hasEndDate($d)
+ {
+ $pattern = '/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/';
+ if (preg_match($pattern, $d, $m)) {
+ return checkdate((int) $m[1], (int) $m[2], (int) $m[3]);
+ } else {
+ return false;
+ }
+ }
+
+ // }}}
+ // {{{ emailOwner()
+
+ /**
+ * Emails the owner the submitted data from the submitted form
+ *
+ * Uses a flexy template to render a nice looking html email.
+ * Fills in the supplied data from the form and doesn't add the
+ * empty fields the user didn't fill in.
+ *
+ * @return boolean result of the mailing
+ * @access protected
+ */
+ protected function emailOwner()
+ {
+ if (!$this->email) {
+ return;
+ }
+
+ $template = new HTML_Template_Flexy($this->flexyOptions);
+ $page = new stdClass();
+ // for comments textarea need to replace newlines with br
+ $this->formData['comments']['element'] = nl2br($this->getSubmitValue('comments'));
+ unset($this->formData['lat'], $this->formData['lon']);
+
+ // these values are required, therefor will always be part of
+ // the formData array
+ $bdate = explode('/', $this->formData['bdate']['element']);
+ $foo = array_map('trim', $bdate);
+ $this->formatValue($foo, '%02d/%02d/%d');
+ $this->formData['bdate']['element'] = $foo;
+
+ $btime = explode('/', $this->formData['btime']['element']);
+ $foo = array_map('trim', $btime);
+ $this->formatValue($foo, '%02d:%02d %s');
+ $this->formData['btime']['element'] = $foo;
+
+ // not required, so check to make sure it exists before trying
+ // to format the value
+ if (isset($this->formData['edate'])) {
+ $edate = explode('/', $this->formData['edate']['element']);
+ $foo = array_map('trim', $edate);
+ $this->formatValue($foo, '%02d/%02d/%d');
+ $this->formData['edate']['element'] = $foo;
+ }
+ if (isset($this->formData['etime'])) {
+ $etime = explode('/', $this->formData['etime']['element']);
+ $foo = array_map('trim', $etime);
+ $this->formatValue($foo, '%02d:%02d %s');
+ $this->formData['etime']['element'] = $foo;
+ }
+
+ $category = $this->eventMapper->fetchCategory(
+ $this->formData['category']['element']
+ );
+ if ($category) {
+ $this->formData['category']['element'] = $category->getName();
+ }
+
+ $page->email_from = FROM_NEWS_EMAIL;
+ $page->subject = $this->subject;
+ $page->formData = $this->formData;
+ $page->eventAdminURL = MEDIA_BASE_URL . 'admin/CommonEvents/index.php?pending=1';
+
+ $template->compile('emailOwner.tpl');
+ $htmlMsg = $template->bufferedOutputObject($page);
+
+ // Text version can't have HTML in it
+ $msg = "{$page->subject}\n\n";
+ $msg .= "From {$page->fname} {$page->lname}\n\n";
+ $msg .= "Information\n\n";
+ foreach ($page->formData as $i) {
+ $msg .= "{$i['label']}: {$i['element']}\n";
+ }
+
+ $crlf = "\n";
+ $mimeMail = new Mail_mime($crlf);
+ $mimeMail->setFrom("{$this->siteName} <{$page->email_from}>");
+ $mimeMail->setSubject($this->subject);
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ $mail = Mail::factory('mail');
+ $body = $mimeMail->get();
+ $headers = $mimeMail->headers();
+
+ $res = $mail->send($this->email, $headers, $body);
+ if (PEAR::isError($res)) {
+ return Toolkit_Common::handleError($res);
+ } else {
+ return $res;
+ }
+ }
+
+ // }}}
+ // {{{ formatValue()
+
+ /**
+ * Format an array into an acceptable string
+ *
+ * @param mixed &$i array values to format or null value for
+ * element that was not filled in
+ * @param string $format string to format values into
+ *
+ * @return string formatted string
+ * @access public
+ */
+ public function formatValue(&$i, $format)
+ {
+ // Allow for 0 to be not empty. This allows for minutes in the
+ // time arrays to be valid if they are on the hour ie. (1:00 pm)
+ $notEmpty = create_function('$v', 'return strlen($v) > 0;');
+ if (is_array($i) && count(array_filter($i, $notEmpty)) == 3) {
+ list($x, $y, $z) = array_values($i);
+ eval("\$i = sprintf('$format', $x, $y, $z);");
+ } else {
+ $i = null;
+ }
+ }
+
+ // }}}
+ // {{{ insertData()
+
+ /**
+ * Inserts contact data into the contact db
+ *
+ * @param array $values submitted values
+ *
+ * @return object result of db insert query
+ * @access protected
+ */
+ protected function insertData($values)
+ {
+ $values = $this->_geocode($values);
+
+ try {
+ // need to set the dates up first
+ $this->formatValue($values['btime'], '%d:%02d %s');
+ $this->formatValue($values['etime'], '%d:%02d %s');
+ $values['description'] = nl2br($values['description']);
+ $values['website'] = preg_replace("/^(http:\/\/)/", "", $values['website']);
+ if ($values['btime']) {
+ $values['starthour'] = $values['btime'];
+ unset($values['btime']);
+ }
+ if ($values['etime']) {
+ $values['endhour'] = $values['etime'];
+ unset($values['etime']);
+ }
+ if ($values['category']) {
+ $values['category'] = $this->eventMapper->fetchCategory(
+ $values['category']
+ );
+ }
+ if (defined('MEMBERS_DB') && MEMBERS_DB) {
+ $event = MemberEvent::createByValues($values);
+ } else {
+ $event = Event::createByValues($values);
+ }
+ return $this->eventMapper->saveEvent($event);
+
+ return false;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ private function _geocode(array $values)
+ {
+ $geocoder = new GeocodeYahoo();
+ if (!$values['address'] && !$values['city'] && !$values['state']) {
+ return $values;
+ }
+ $address = array(
+ 'city' => $values['city'],
+ 'state' => $values['state'],
+ 'zip' => $values['zip'],
+ );
+ if (!empty($values['address'])) {
+ $address['street'] = $values['address'];
+ }
+ try {
+ $response = $geocoder->geocodeAddress($address);
+ $responseArray = unserialize($response);
+ if ($responseArray['ResultSet']['Result'][0]['Latitude']) {
+ $values['lat'] = $responseArray['ResultSet']['Result'][0]['Latitude'];
+ $values['lon'] = $responseArray['ResultSet']['Result'][0]['Longitude'];
+ } else {
+ $values['lat'] = $responseArray['ResultSet']['Result']['Latitude'];
+ $values['lon'] = $responseArray['ResultSet']['Result']['Longitude'];
+ }
+
+ return $values;
+ } catch (BadMethodCallException $e) {
+ Toolkit_Logger::logException('Invalid Arg', $e);
+ } catch (Exception $e) {
+ Toolkit_Logger::logException('Yahoo GeoCode', $e);
+ }
+
+ }
+ // {{{ processData()
+
+ /**
+ * Handles how to process the form when submitted
+ *
+ * @param array $values Form submitted values
+ *
+ * @return array Result of Insert / Update function
+ * @access protected
+ */
+ public function processData($values)
+ {
+ // Form data used for the insert/update sql queries and
+ // the form email.
+ $e = array();
+ $this->setFormData($e);
+
+ // Get rid of any defined un-needed elements.
+ // un-needed elements after the form is submitted are defined
+ // by the ending _rmv name.
+ foreach ($values as $k => &$v) {
+ if (!is_array($v)) {
+ $values[$k] = preg_replace("/\r/", "\n", $v);
+ }
+ if (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ }
+ $values['create_date'] = date('m/d/Y');
+
+ return $this->insertData($values);
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Custom rendering templates for special fields on the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer = $this->defaultRenderer();
+ $required = '<!-- BEGIN required --><span class="req">*</span><!-- END required -->';
+ $error = '<!-- BEGIN error --><div class="req">{error}</div><!-- END error -->';
+
+ $renderer->setElementTemplate('<tr><td colspan="2">' . $required . '{label}' . $error . '{element}</td></tr>', 'descr');
+ $renderer->setElementTemplate('<tr align="center"><td colspan="2">' . $required . '{label}' . $error . '{element}</td></tr>', 'submit_rmv');
+
+ if ($this->useCaptcha) {
+ $renderer->setElementTemplate('<tr><td class="labelcell"><label>{label}</label></td><td class="fieldcell captcha">{element}</td></tr>', 'captcha_question');
+ $renderer->setElementTemplate('<tr><td class="labelcell">' . $required . '<label>{label}</label></td><td class="fieldcell">' . $error . '{element}<span class="tooltip" title="Verification Code|To help us distinguish between information submitted by individuals and those automatically entered by software robots, please type the letters shown.">What is this?</span></td></tr>', 'captcha_rmv');
+ }
+ }
+
+ // }}}
+ // {{{ toHtml()
+
+ /**
+ * Handles how to display the current step the user is at in the form
+ *
+ * destroying and resetting the captcha value dis-allows someone from
+ * re-sending a form on a previous captcha.
+ *
+ * @return string form HTML state
+ * @access public
+ */
+ public function toHtml()
+ {
+ $this->setupRenderers();
+ if ($this->validate()) {
+ $this->captchaQuestion->destroy();
+ $this->cleanForm();
+
+ if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) {
+ $this->freeze();
+ $this->emailOwner();
+ $output = $this->successMsg;
+ }
+ $this->sent = true;
+ } elseif ($this->isSubmitted()) {
+ if ($this->useCaptcha) {
+ $this->captchaQuestion->destroy();
+ $this->captchaAnswer->setValue('');
+ }
+ $output = $this->errorMsg;
+ $GLOBALS['topScripts'][]
+ = MEDIA_APP_BASE_URL
+ . 'libjs/jqueryui/1.8.13/js/jquery-ui-1.8.13.custom.min.js';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_APP_BASE_URL
+ . 'libjs/jqueryui/1.8.13/development-bundle/themes/base/jquery.ui.all.css';
+ $GLOBALS['bottomScripts'][] = MEDIA_APP_BASE_URL . 'libjs/textlimit.js';
+ $GLOBALS['topScripts'][]
+ = 'http://maps.googleapis.com/maps/api/js?sensor=true';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Maps/geoCoder.js';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Events/libjs/addEvent.js';
+ $output .= parent::toHtml();
+ } else {
+ if ($this->useCaptcha) {
+ $this->captchaQuestion->destroy();
+ $this->captchaAnswer->setValue('');
+ }
+ $GLOBALS['topScripts'][]
+ = MEDIA_APP_BASE_URL
+ . 'libjs/jqueryui/1.8.13/js/jquery-ui-1.8.13.custom.min.js';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_APP_BASE_URL
+ . 'libjs/jqueryui/1.8.13/development-bundle/themes/base/jquery.ui.all.css';
+ $GLOBALS['bottomScripts'][] = MEDIA_APP_BASE_URL . 'libjs/textlimit.js';
+ $GLOBALS['topScripts'][]
+ = 'http://maps.googleapis.com/maps/api/js?sensor=true';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Maps/geoCoder.js';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Events/libjs/addEvent.js';
+ $output = parent::toHtml();
+ }
+ return $output;
+ }
+
+ // }}}
+}
+
+?>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-"http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<title>{pageTitle:h}</title>
-<meta http-equiv="content-type" content="text/html;charset=utf-8">
-<meta name="description" content="{metaTags:h}">
-<meta http-equiv="imagetoolbar" content="no">
-<meta http-equiv="imagetoolbar" content="false">
-{styles:h}
-{topScripts:h}
-</head>
-<body id="inside"><!-- body id home on homepage only , #inside for inside pages-->
-<div id="wrapper">
- <div id="wrapperInner">
- <div id="top">
- <a href="baseurl/index.php">
- <img id="logo" src="baseurl/assets/logo.png" width="520" height="50">
- </a>
- </div><!-- /#top -->
- <ul id="nav">
- <li><a href="#">Home</a></li>
- <li><a href="#">Services</a></li>
- <li><a href="#">Patient Information</a></li>
- <li><a href="#">About Us</a></li>
- <li><a href="#">Location</a></li>
- <li id="lastli"><a href="#">Contact Us</a></li>
- </ul>
- <div id="column">
- <div id="subnav"><!-- only if there are subpages -->
- <h2>Services</h2>
- <ul>
- <li><a href="#">Navigation Name</a></li>
- <li><a href="#">Halloisann hu</a></li>
- <li><a href="#">Lorem Ipsum</a></li>
- <li><a href="#">Navigator Tools</a></li>
- <li><a href="#">Nav</a></li>
- <li><a href="#">Navigation Name</a></li>
- <li><a href="#">Halloisann hu</a></li>
- <li><a href="#">Lorem Ipsum</a></li>
- <li><a href="#">Navigator Tools</a></li>
- <li></li>
- </ul>
- </div><!-- /#subnav -->
- </div><!-- /#column -->
- <div id="main">
- <div id="toolbox">
- <div id="category">
- <h1>Page Header</h1>
- <div class="imageright">
- <img src="baseurl/assets/toolboxTMP.gif" width="325" height="218" alt="toolboxTMP (26K)">
- <div class="imagecaption">This is the imagecaption</div>
- </div><!-- /..imageright -->
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- </div><!-- /#category -->
- <div class="listing">
- <h2>Header</h2>
- <div class="imageleft">
- <img src="baseurl/assets/toolboxTMP.gif" width="325" height="218" alt="toolboxTMP (26K)">
- <div class="imagecaption">This is the imagecaption</div>
- </div><!-- /..imageleft -->
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- </div><!-- /.listin\g -->
- <div class="listing">
- <h2>Header</h2>
- <div class="imageright">
- <img src="baseurl/assets/toolboxTMP.gif" width="325" height="218" alt="toolboxTMP (26K)">
- <div class="imagecaption">This is the imagecaption</div>
- </div><!-- /..imageright -->
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- <p>Located in the exact center of Northern Michigan on the 45th parallel, Gaylord is unique because of its stunning surroundings, up north ambience and easy commuting access. </p>
- </div><!-- /.listin\g -->
- </div><!-- /#toolbox -->
- </div><!-- /#main -->
- <div id="footer">
- <p>Dermatology Associates of Northern Michigan, P.C. 2240 Mitchell Park Petoskey, MI 49770 · 231-487-2230</p>
- </div>
- <ul id="accreditations">
- <li id="aAAD">AAD</li>
- <li id="aABD">ABD</li>
- <li id="aACMS">ACMS</li>
- <li id="aASDS">ASDS</li>
- </ul>
- <div id="copyright">
- Copyright©<?php echo date('Y');?> {siteName:h} - Produced by <a href="http://www.gaslightmedia.com">Gaslight Media</a>, All Rights Reserved.
- </div><!-- /#copyright -->
- </div><!-- /#wrapperInner" -->
-</div><!-- /#wrapper -->
-{bottomScripts:h}
-</body>
-</html>
+<!doctype html>
+<html class="no-js" lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>{pageTitle:h}</title>
+ {styles:h}
+ <link rel="stylesheet" href="{mediaBaseURL:h}css/foundation.css">
+ <link rel="stylesheet" href="{mediaBaseURL:h}styles.css">
+ {topScripts:h}
+
+ </head>
+ {if:isHomePage}
+ <body id="home">
+ {else:}
+ <body id="inside" class="pid{pageId} top{parentPageId}">
+ {end:}
+ <div class="off-canvas-wrap" data-offcanvas>
+ <div class="inner-wrap">
+ <nav class="tab-bar show-for-small">
+ <section class="left-small">
+ <a class="left-off-canvas-toggle menu-icon" href="#"><span></span></a>
+ </section>
+ </nav>
+
+ <!-- Off Canvas Menu -->
+ <aside class="left-off-canvas-menu" id="mobilenav">
+ <!-- whatever you want goes here -->
+ {mainNav:h}
+
+ </aside>
+
+
+ <section>
+ <div class="row">
+ <div class="large-12 columns" id="header">
+ <a href="#">
+ <img src="assets/logo.png" id="logo">
+ </a>
+ <div id="search">
+ <form action="#">
+ <input type="text" id="searchText">
+ <input type="submit" id="searchSubmit">
+ </form>
+ </div>
+ <nav class="clearfix">
+ <ul class="clearfix">
+ <li>
+ <a href="#">Departments</a>
+ </li>
+ <li>
+ <a href="#">Documents</a>
+ </li>
+ <li>
+ <a href="#">Calendars</a>
+ </li>
+ <li>
+ <a href="#">Contact</a>
+ </li>
+ </ul>
+ </nav>
+ </div>
+ </div>
+
+ <div id="subnav">
+ {sideNav:h}
+ </div>
+
+ <div class="row" id="homeSlide" homepageonly>
+ <div class="large-9 columns">
+ <div id="slideshow">
+ <ul>
+ <li>
+ <img src="tmpSlidehow.jpg">
+ </li>
+ </ul>
+ </div>
+
+ </div>
+ <div class="large-3 columns">
+ <div id="homepage_events_wrapper" flexy:if="hasEvents">
+ <div id="cEventMeetings">Meetings</div>
+ <div id="cEventMore"><a href="{baseURLDefined:h}events-79/">More Events</a></div>
+ <div id="eventCalendarWrapper">{smallCal:h}</div>
+ <div id="eventItemWrapper">
+ <a flexy:foreach="events,v" href="{v[href]:h}" class="cEventItem">
+ <span class="cEventTitle">{v[header]}</span>
+ <span class="cEventDate">{v[dates]}</span>
+ <span class="cEventTimes" flexy:if="v[times]">{v[times]}</span>
+ <span class="cEventCategory" flexy:if="v[cat]"><b>Category:</b> {v[cat]}</span>
+ <span class="cEventDescription" flexy:if="v[intro]">{v[intro]}</span>
+ <span class="cEventLocation" flexy:if="v[loc]"><b>Location:</b>
+ {if:v[loc][place]}
+ {v[loc][place]},
+ {end:}
+ {if:v[loc][address]}
+ {v[loc][address]},
+ {end:}
+ {if:v[loc][city]}
+ {v[loc][city]}, {v[loc][state]} {v[loc][zip]}
+ {end:}
+ </span>
+ </a><!-- /.cEventItem -->
+ </div><!-- /#eventItemWrapper -->
+ </div><!-- /#homepage_events_wrapper -->
+ </div>
+ </div>
+ <div class="row">
+ <div class="large-12 columns">
+ <div id="toolbox">
+ {toolboxContent:h}
+ </div>
+ <section id="hHlines" class="opensearchserver.ignore">
+ <ul class="small-block-grid-2 medium-block-grid-3">
+ <li class="hHlinesItem">
+ <a href="#">
+ <img src="tmpBlock.jpg" alt="">
+ <i>Recreation Department</i>
+ </a>
+ </li>
+ <li class="hHlinesItem">
+ <a href="#">
+ <img src="tmpBlock.jpg" alt="">
+ <i>Forms</i>
+ </a>
+ </li>
+ <li class="hHlinesItem">
+ <a href="#">
+ <img src="tmpBlock.jpg" alt="">
+ <i>Municiple Codes</i>
+ </a>
+ </li>
+ </ul>
+ </section>
+ </div>
+ </div>
+
+ <div class="row" id="footer">
+ <div class="small-6 medium-3 large-3 columns">
+ <div>
+ <a href="#">City Clerk</a>
+ (906) 847-3702
+ <a href="#">clerk@cityofmi.org</a>
+ </div>
+ <div>
+ <a href="#">Mayor's Assistant</a>
+ (906) 847-6556
+ <a href="#">assistant@cityofmi.org</a>
+ </div>
+ <div>
+ <a href="#">Assessor</a>
+ (231) 348-9800
+ <a href="#">jstakoe@nappraisal.net</a>
+ </div>
+ </div>
+
+ <div class="small-6 medium-3 large-3 columns">
+ <div>
+ <a href="#">Department of Public Works</a>
+ (906) 847-6130
+ <a href="#">midpw@cityofmi.org</a>
+ </div>
+ <div>
+ <a href="#">Building and Zoning</a>
+ (906) 847-4035
+ <a href="#">djd@cityofmi.org</a>
+ <a href="#">kep@cityofmi.org</a>
+ </div>
+ <div>
+ <a href="#">Treasurer</a>
+ (906) 847-6002
+ <a href="#">treasurer@cityofmi.org</a>
+ </div>
+ </div>
+ <div class="small-6 medium-3 large-3 columns">
+ <div>
+ <a href="#">Recreation Department</a>
+ (906) 298-0333
+ <a href="#">recdept@cityofmi.org</a>
+ </div>
+ <div>
+ <a href="#">Public Library</a>
+ (906) 847-3421
+ <a href="#">mcislib@mackisland.com</a>
+ </div>
+ <div>
+ <a href="#">Stuart House</a>
+ (906) 847-8181
+ </div>
+ </div>
+ <div class="small-6 medium-3 large-3 columns">
+ <div>
+ <a href="#">Emergencies</a>
+ 911
+ </div>
+ <div>
+ <a href="#">Police Department (non-emergency)</a>
+ (906) 847-3345
+ <a href="#">midpchief@cityofmi.org</a>
+ </div>
+ <div>
+ Fire Department (non-emergency)
+ (906) 847-8159
+ <a href="#">mifd@cityofmi.org</a>
+ </div>
+ <div>
+ Medical Center (non-emergency)
+ (906) 847-3582
+ </div>
+ </div>
+ </div>
+ </section>
+
+
+
+ <!-- close the off-canvas menu -->
+ <a class="exit-off-canvas"></a>
+ </div>
+ </div>
+ {bottomScripts:h}
+
+ <script>
+ $(document).foundation({
+ offcanvas: {
+ open_method: 'move',
+ close_on_click: true
+ }
+ });
+ </script>
+
+ </body>
+</html>
\ No newline at end of file