* Copyright © 2014 Strangecode, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* HTML()
*
* Tools for building HTML from PHP data.
*
* @author Quinn Comendant
* @version 1.0
* @since 11 Sep 2014 21:08:06
*
* Example of use:
---------------------------------------------------------------------
echo HTML::buttons(array(
array('name' => 'btn_submit', 'value' => _("Save changes"), 'class' => 'small button', 'accesskey' => 's'),
array('name' => 'btn_reset', 'value' => _("Reset"), 'class' => 'small button secondary', 'accesskey' => 'r'),
array('name' => 'btn_cancel', 'value' => _("Cancel"), 'class' => 'small button secondary', 'accesskey' => 'c'),
));
---------------------------------------------------------------------
*/
class HTML
{
// Browsers add names and ids of form controls as properties to the FORM. This results in the properties of the form being replaced.
// Use this list to warn the programmer if he uses an unsafe name.
// http://jibbering.com/faq/names/unsafe_names.html
static $unsafe_form_control_names = array('accept','acceptCharset','action','addBehavior','addEventListener','addEventSource','addRepetitionBlock','addRepetitionBlockByIndex','all','appendChild','applyElement','ariaBusy','ariaChecked','ariaControls','ariaDescribability','ariaDisabled','ariaExpanded','ariaFlowto','ariaHaspopup','ariaHidden','ariaInvalid','ariaLabelledby','ariaLevel','ariaMultiselect','ariaOwns','ariaPosinset','ariaPressed','ariaReadonly','ariaRequired','ariaSecret','ariaSelected','ariaSetsize','ariaValuemax','ariaValuemin','ariaValuenow','attachEvent','attributes','ATTRIBUTE_NODE','autocomplete','baseURI','behaviorUrns','blockDiraction','blur','canHaveChildren','canHaveHTML','CDATA_SECTION_NODE','checkValidity','childElementCount','childNodes','children','className','clearAttributes','click','clientHeight','clientLeft','clientTop','clientWidth','cloneNode','COMMENT_NODE','compareDocumentPosition','componentFromPoint','constructor','contains','contentEditable','currentStyle','data','detachEvent','dir','dispatchEvent','dispatchFormChange','dispatchFormInput','document','DOCUMENT_FRAGMENT_NODE','DOCUMENT_NODE','DOCUMENT_POSITION_CONTAINED_BY','DOCUMENT_POSITION_CONTAINS','DOCUMENT_POSITION_DISCONNECTED','DOCUMENT_POSITION_FOLLOWING','DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC','DOCUMENT_POSITION_PRECEDING','DOCUMENT_TYPE_NODE','dragDrop','elements','ELEMENT_NODE','encoding','enctype','ENTITY_NODE','ENTITY_REFERENCE_NODE','fireEvent','firstChild','firstElementChild','focus','getAdjacentText','getAttribute','getAttributeNode','getAttributeNodeNS','getAttributeNS','getBoundingClientRect','getClientRects','getElementsByClassName','getElementsByTagName','getElementsByTagNameNS','getExpression','getFeature','getUserData','hasAttribute','hasAttributeNS','hasAttributes','hasChildNodes','hasOwnProperty','hideFocus','id','innerHTML','innerText','insertAdjacentElement','insertAdjacentHTML','insertAdjacentText','insertBefore','isContentEditable','isDefaultNamespace','isDefaultNamespaceURI','isDisabled','isEqualNode','isMultiLine','isPrototypeOf','isSameNode','isSupported','isTextEdit','item','lang','language','lastChild','lastElementChild','length','localName',
'lookupPrefix','mergeAttributes','method','moveRepetitionBlock','msBlockProgression','msBoxSizing','name','namedItem','namespaceURI','nextSibling','nodeName','nodeType','nodeValue','normalize','NOTATION_NODE','offsetHeight','offsetWidth','onabort','onactivate','onbeforeactivate','onbeforecopy','onbeforecut','onbeforedeactivate','onbeforeeditfocus','onbeforepaste','onblur','onchage','onclick','onclosecapture','oncontextmenu','oncopy','oncut','ondblclick','ondeactivate','ondrag','ondragend','ondragenter','ondragleave','ondragover','onerror','onfocus','onfocusin','onfocusout','onhelp','oninput','onkeydown','onkeypress','onkeyup','onmousedown','onmouseenter','onmouseleave','onmousemove','onmousemultiwheel','onmouseout','onmouseover','onmouseup','onmousewheel','onmove','onmoveend','onmovestart','onOffBehavior','onpaste','onpropertychange','onreadystatechange','onresize','onresizeend','onresizestart','onscroll','onsearch','onselect','onselectstart','ontimeerror','onunload','outerHTML','outerText','ownerDocument','parentNode','parentTextEdit','prefix','previousElementSibling','previousSibling','PROCESSING_INSTRUCTION_NODE','propertyIsEnumerable','querySelector','querySelectorAll','quotes','releaseCapture','removeAttribute','removeAttributeNode','removeAttributeNS','removeBehavior','removeChild','removeEventListener','removeEventSource','removeExpression','removeNode','removeRepetitionBlock','repeatMax','repeatMin','repeatStart','repetitionBlocks','repetitionIndex','repetitionTemplate','repetitionType','replace','replaceAdjacentText','replaceChild','replaceNode','reset','resetFromData','role','runtimeStyle','schemaTypeInfo','scopeName','scrollByLines','scrollByPages','scrollHeight','scrollIntoView','scrollLeft','scrollTop','scrollWidth','selectNodes','selectSingleNode','setActive','setAttributeNode','setAttributeNodeNS','setAttributeNS','setCapture','setExpression','setIdAttribute','setIdAttributeNode','setIdAttributeNS','setUserData','sourceIndex','spellcheck','style','submit','swapNode','tabIndex','tagName','tagUrn','target','templateElements','text','textContent','TEXT_NODE','title','toLocaleString','toString','uniqueID','unselectable','unwatch','urns','valueOf','watch','window');
/**
* Prints submit buttons based on given array of submit button names and titles. If the array includes an 'href' key, the
* button is created using a otherwise an is used.
*
* @access public
* @param array $buttons Array of buttons, the key being the button name, and value being the title of the button.
* @return void
* @author Quinn Comendant
* @version 1.0
* @since 12 Sep 2014 00:17:38
*/
static public function printButtons($buttons=array(), $class='button-group')
{
$app =& App::getInstance();
if (!isset($buttons[0]) || !is_array($buttons[0])) {
$app =& App::getInstance();
$app->logMsg(sprintf('Incorrect parameters passed to %s: %s', __METHHOD__, getDump($options)), LOG_NOTICE, __FILE__, __LINE__);
return false;
}
if (empty($buttons)) {
return '';
}
?> $b) {
$defaults = array();
$defaults['type'] = isset($b['type']) ? $b['type'] : 'submit';
$b = array_merge($defaults, $b);
if (isset($b['href'])) {
echo '- null)) as $key => $value) {
printf(' %s="%s"', oTxt($key), oTxt($value));
}
echo '>' . oTxt($b['value']) . '
';
} else if (isset($b['name'])) {
if (in_array($b['name'], self::$unsafe_form_control_names)) {
$app->logMsg(sprintf('Unsafe form control name: %s', $b['name']), LOG_NOTICE, __FILE__, __LINE__);
}
$defaults['id'] = isset($b['id']) ? $b['id'] : sprintf('sc-%s-button', $b['name']);
echo '- $value) {
printf(' %s="%s"', oTxt($key), oTxt($value));
}
echo ' />
';
} else {
$app->logMsg(sprintf('Button missing name or href: %s', getDump($b)), LOG_ERR, __FILE__, __LINE__);
continue;
}
}
?>
* @version 1.0
* @since 12 Sep 2014 11:43:23
*/
static public function getSelectOptions($db_table, $key_column, $val_column, $preselected, $first=false, $extra_clause='', $sql_format='SELECT %1$s, %2$s FROM %3$s %4$s')
{
$db =& DB::getInstance();
// Sometimes preselected comes as a comma list.
if (!is_array($preselected)) {
$preselected = array($preselected);
}
$options = array();
if (true === $first) {
// Include a blank first option.
$options[] = array(
'value' => '',
'selected' => in_array('', $preselected),
'text' => '',
'raw' => null,
);
} else if (is_array($first)) {
// When the 'blank' first option needs a specific key->val pair.
foreach ($first as $key => $val) {
$options[] = array(
'value' => $key,
'selected' => in_array($key, $preselected),
'text' => $val,
'raw' => null,
);
}
}
$db =& DB::getInstance();
$qid = $db->query(sprintf($sql_format, $key_column, $val_column, $db_table, $extra_clause), false);
while ($row = mysql_fetch_assoc($qid)) {
$options[] = array(
'value' => $row[$val_column],
'selected' => in_array($row[$val_column], $preselected),
'text' => $row[$key_column],
'raw' => $row,
);
}
return $options;
}
/*
*
*
* @access public
* @param array $options Array of options, with keys: value, selected, text
* @param array $deselected Array of values to disable in options.
* @return array Same options, but those with a value matching an element in $deselected will have a 'disabled' element of true.
* @author Quinn Comendant
* @version 1.0
* @since 24 Jul 2015 01:41:33
*/
static public function disableSelectOptions($options, $deselected)
{
$app =& App::getInstance();
$n = sizeof($options);
for ($i=0; $i < $n; $i++) {
$app->logMsg(sprintf('Disable check: %s == %s', $options[$i]['value'], getDump($deselected)), LOG_DEBUG, __FILE__, __LINE__);
$options[$i]['disabled'] = in_array($options[$i]['value'], $deselected);
}
return $options;
}
/**
* Get an array of option fields for a select form. Works only with enum or set
* data types in table columns.
*
* @param string $db_table Database table to lookup
* @param string $db_col Database column to lookup
* @param string $preselected The currently selected value of the menu. compared to the $val_column
* @param bool $first Optional first item; set true for a blank item, array for item with name and value.
* @param bool $sort Sort the output.
*/
static public function getSelectOptionsEnum($db_table, $db_col, $preselected, $first=false, $sort=false)
{
// Sometimes preselected comes as a comma list.
if (!is_array($preselected)) {
$preselected = array($preselected);
}
$options = array();
if (true === $first) {
// Include a blank first option.
$options[] = array(
'value' => '',
'selected' => in_array('', $preselected),
'text' => '',
);
} else if (is_array($first)) {
// When the 'blank' first option needs a specific key->val pair.
foreach ($first as $key => $val) {
$options[] = array(
'value' => $key,
'selected' => in_array($key, $preselected),
'text' => $val,
);
}
}
$db =& DB::getInstance();
$values = $db->getEnumValues($db_table, $db_col, $sort);
foreach ($values as $v) {
$options[] = array(
'value' => $v,
'selected' => in_array($v, $preselected),
'text' => $v,
);
}
return $options;
}
/**
* Prints select menu options with the specified array of keys and values.
*
*/
static public function printSelectOptions($options)
{
if (!isset($options) || !is_array($options)) {
$app =& App::getInstance();
$app->logMsg(sprintf('Incorrect parameters passed to %s: %s', __METHHOD__, getDump($options)), LOG_NOTICE, __FILE__, __LINE__);
return false;
}
if (empty($options)) {
return '';
}
foreach ($options as $o) {
printf('',
oTxt($o['value']),
(isset($o['class']) && sprintf(' class="%s"', oTxt($o['class'])) ? : ''),
(isset($o['selected']) && oTxt($o['selected']) ? ' selected="selected"' : ''),
(isset($o['disabled']) && oTxt($o['disabled']) ? ' disabled="disabled"' : ''),
oTxt($o['text'])
);
}
}
/*
* Print select options for a list of US states.
*
* @access public
* @param string $preselected the currently selected value of the menu. compared to the $val_column
* @return void
* @author Quinn Comendant
* @since 12 Feb 2020 22:26:34
*/
static public function printStatesSelectOptions($preselected='', $first=false)
{
$options = ['AL' => 'Alabama', 'AK' => 'Alaska', 'AZ' => 'Arizona', 'AR' => 'Arkansas', 'CA' => 'California', 'CO' => 'Colorado', 'CT' => 'Connecticut', 'DE' => 'Delaware', 'DC' => 'District Of Columbia', 'FL' => 'Florida', 'GA' => 'Georgia', 'HI' => 'Hawaii', 'ID' => 'Idaho', 'IL' => 'Illinois', 'IN' => 'Indiana', 'IA' => 'Iowa', 'KS' => 'Kansas', 'KY' => 'Kentucky', 'LA' => 'Louisiana', 'ME' => 'Maine', 'MD' => 'Maryland', 'MA' => 'Massachusetts', 'MI' => 'Michigan', 'MN' => 'Minnesota', 'MS' => 'Mississippi', 'MO' => 'Missouri', 'MT' => 'Montana', 'NE' => 'Nebraska', 'NV' => 'Nevada', 'NH' => 'New Hampshire', 'NJ' => 'New Jersey', 'NM' => 'New Mexico', 'NY' => 'New York', 'NC' => 'North Carolina', 'ND' => 'North Dakota', 'OH' => 'Ohio', 'OK' => 'Oklahoma', 'OR' => 'Oregon', 'PA' => 'Pennsylvania', 'RI' => 'Rhode Island', 'SC' => 'South Carolina', 'SD' => 'South Dakota', 'TN' => 'Tennessee', 'TX' => 'Texas', 'UT' => 'Utah', 'VT' => 'Vermont', 'VA' => 'Virginia', 'WA' => 'Washington', 'WV' => 'West Virginia', 'WI' => 'Wisconsin', 'WY' => 'Wyoming'];
if (true === $first) {
// Include a blank first option.
$options = array_merge(['' => ''], $options);
} else if (is_array($first)) {
// When the 'blank' first option needs a specific key->val pair.
foreach ($first as $key => $val) {
$options = array_merge([$key => $val], $options);
}
}
foreach ($options as $value => $text) {
printf('',
oTxt($value),
$preselected == $value ? ' selected="selected"' : '',
oTxt($text)
);
}
}
/**
* Get a Gravatar URL for a specified email address.
*
* @param string $email The email address
* @param string $size Size in pixels, defaults to 80px [ 1 - 2048 ]
* @param string $d Default imageset to use [ 404 | mp | identicon | monsterid | wavatar | retro | robohash | blank ]
* See what defaults look like at https://en.gravatar.com/site/implement/images/
* @param string $r Maximum rating (inclusive) [ g | pg | r | x ]
* @return String containing a URL to a gravatar image.
* @source http://gravatar.com/site/implement/images/php/
*/
static public function getGravatarURL($email, $size=80, $defset='mp', $rating='pg') {
return sprintf('https://www.gravatar.com/avatar/%s?s=%s&d=%s&r=%s',
md5(strtolower(trim($email))),
$size,
$defset,
$rating
);
}
}