if ( ! class_exists( 'GFForms' ) ) {
die();
}
class GF_Field_Number extends GF_Field {
public $type = 'number';
public function get_form_editor_field_title() {
return esc_attr__( 'Number', 'gravityforms' );
}
/**
* Returns the field's form editor description.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_description() {
return esc_attr__( 'Allows users to enter a number.', 'gravityforms' );
}
/**
* Returns the field's form editor icon.
*
* This could be an icon url or a gform-icon class.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_icon() {
return 'gform-icon--numbers-alt';
}
function get_form_editor_field_settings() {
return array(
'conditional_logic_field_setting',
'prepopulate_field_setting',
'error_message_setting',
'label_setting',
'label_placement_setting',
'admin_label_setting',
'size_setting',
'number_format_setting',
'range_setting',
'rules_setting',
'visibility_setting',
'duplicate_setting',
'default_value_setting',
'placeholder_setting',
'description_setting',
'css_class_setting',
'calculation_setting',
'autocomplete_setting',
);
}
public function is_conditional_logic_supported() {
return true;
}
public function get_value_submission( $field_values, $get_from_post_global_var = true ) {
$value = $this->get_input_value_submission( 'input_' . $this->id, $this->inputName, $field_values, $get_from_post_global_var );
if ( is_array( $value ) ) {
$value = array_map( 'trim', $value );
foreach ( $value as &$v ) {
$v = trim( $v );
$v = $this->clean_value( $v );
}
} else {
if ( is_string( $value ) ) {
$value = trim( $value );
$value = $this->clean_value( $value );
}
}
return $value;
}
/**
* Ensures the POST value is in the correct number format.
*
* @since 2.4
*
* @param $value
*
* @return bool|float|string
*/
public function clean_value( $value ) {
if ( $this->numberFormat == 'currency' ) {
$currency = new RGCurrency( GFCommon::get_currency() );
$value = $currency->to_number( $value );
} elseif ( $this->numberFormat == 'decimal_comma' ) {
$value = GFCommon::clean_number( $value, 'decimal_comma' );
} elseif ( $this->numberFormat == 'decimal_dot' ) {
$value = GFCommon::clean_number( $value, 'decimal_dot' );
}
return $value;
}
public function validate( $value, $form ) {
// The POST value has already been converted from currency or decimal_comma to decimal_dot and then cleaned in get_field_value().
$value = GFCommon::maybe_add_leading_zero( $value );
// Raw value will be tested against the is_numeric() function to make sure it is in the right format.
// If the POST value is an array then the field is inside a repeater so use $value.
$raw_value = isset( $_POST[ 'input_' . $this->id ] ) && ! is_array( $_POST[ 'input_' . $this->id ] ) ? GFCommon::maybe_add_leading_zero( rgpost( 'input_' . $this->id ) ) : $value; // phpcs:ignore WordPress.Security.NonceVerification.Missing
$has_raw_value = ! rgblank( trim( $raw_value ) );
$requires_valid_number = $has_raw_value && ! $this->has_calculation();
$is_valid_number = $this->validate_range( $value ) && GFCommon::is_numeric( $raw_value, $this->numberFormat );
if ( $requires_valid_number && ! $is_valid_number ) {
$this->failed_validation = true;
$this->validation_message = empty( $this->errorMessage ) ? $this->get_range_message() : $this->errorMessage;
} elseif ( $this->type == 'quantity' && $has_raw_value ) {
if ( intval( $value ) != $value ) {
$this->failed_validation = true;
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'Please enter a valid quantity. Quantity cannot contain decimals.', 'gravityforms' ) : $this->errorMessage;
} elseif ( ( ! is_numeric( $value ) || intval( $value ) != floatval( $value ) || intval( $value ) < 0 ) ) {
$this->failed_validation = true;
$this->validation_message = empty( $this->errorMessage ) ? esc_html__( 'Please enter a valid quantity', 'gravityforms' ) : $this->errorMessage;
}
}
}
/**
* Is the given value considered empty for this field.
*
* Adds a check to the parent method because a value of 0 returns a false positive.
*
* @since 2.7.1
*
* @param $value
*
* @return bool
*/
public function is_value_empty( $value ) {
$empty = parent::is_value_empty( $value );
if ( $empty && ! rgblank( $value ) ) {
return false;
}
return $empty;
}
/**
* Validates the range of the number according to the field settings.
*
* @param string $value A decimal_dot formatted string
*
* @return true|false True on valid or false on invalid
*/
private function validate_range( $value ) {
if ( ! GFCommon::is_numeric( $value, 'decimal_dot' ) ) {
return false;
}
$numeric_min = $this->numberFormat == 'decimal_comma' ? GFCommon::clean_number( $this->rangeMin, 'decimal_comma' ) : $this->rangeMin;
$numeric_max = $this->numberFormat == 'decimal_comma' ? GFCommon::clean_number( $this->rangeMax, 'decimal_comma' ) : $this->rangeMax;
if ( ( is_numeric( $numeric_min ) && $value < $numeric_min ) ||
( is_numeric( $numeric_max ) && $value > $numeric_max )
) {
return false;
} else {
return true;
}
}
public function get_range_message() {
$min = $this->rangeMin;
$max = $this->rangeMax;
$numeric_min = $min;
$numeric_max = $max;
if ( $this->numberFormat == 'decimal_comma' ) {
$numeric_min = empty( $min ) ? '' : GFCommon::clean_number( $min, 'decimal_comma', '' );
$numeric_max = empty( $max ) ? '' : GFCommon::clean_number( $max, 'decimal_comma', '' );
}
$message = '';
if ( is_numeric( $numeric_min ) && is_numeric( $numeric_max ) ) {
$message = sprintf( esc_html__( 'Please enter a number from %1$s to %2$s.', 'gravityforms' ), "$min ", "$max " );
} elseif ( is_numeric( $numeric_min ) ) {
$message = sprintf( esc_html__( 'Please enter a number greater than or equal to %s.', 'gravityforms' ), "$min " );
} elseif ( is_numeric( $numeric_max ) ) {
$message = sprintf( esc_html__( 'Please enter a number less than or equal to %s.', 'gravityforms' ), "$max " );
} elseif ( $this->failed_validation ) {
$message = esc_html__( 'Please enter a valid number.', 'gravityforms' );
}
return $message;
}
public function get_field_input( $form, $value = '', $entry = null ) {
$is_entry_detail = $this->is_entry_detail();
$is_form_editor = $this->is_form_editor();
$form_id = $form['id'];
$id = intval( $this->id );
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
$size = $this->size;
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
$class_suffix = $is_entry_detail ? '_admin' : '';
$class_read_only = ( ! $is_entry_detail && ! $is_form_editor ) && $this->has_calculation() ? ' gform-text-input-reset' : '';
$class = esc_attr( $size . $class_suffix . $class_read_only );
$instruction = '';
$read_only = '';
if ( ! $is_entry_detail && ! $is_form_editor ) {
if ( $this->has_calculation() ) {
// calculation-enabled fields should be read only
$read_only = 'readonly="readonly"';
} else {
$message = $this->get_range_message();
$validation_class = $this->failed_validation ? 'validation_message' : '';
if ( ! $this->failed_validation && ! empty( $message ) && empty( $this->errorMessage ) ) {
$instruction = "
" . $message . '
';
}
}
} elseif ( rgget( 'view' ) == 'entry' ) {
$value = GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ) );
}
$html_input_type = ! $this->has_calculation() && ( $this->numberFormat != 'currency' && $this->numberFormat != 'decimal_comma' ) ? 'number' : 'text'; // chrome does not allow number fields to have commas, calculations and currency values display numbers with commas
$step_attr = "step='any'";
$min = $this->rangeMin;
$max = $this->rangeMax;
$min_attr = is_numeric( $min ) ? "min='{$min}'" : '';
$max_attr = is_numeric( $max ) ? "max='{$max}'" : '';
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', $html_input_type == 'text', $this );
$value = GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ), $include_thousands_sep );
$placeholder_attribute = $this->get_field_placeholder_attribute();
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
$describedby_extra_id = '' == $instruction ? array() : array( "gfield_instruction_{$this->formId}_{$this->id}" );
$aria_describedby = $this->get_aria_describedby( $describedby_extra_id );
$autocomplete_attribute = $this->enableAutocomplete ? $this->get_field_autocomplete_attribute() : '';
$tabindex = $this->get_tabindex();
$input = sprintf( " %s
", $id, $field_id, esc_attr( $value ), esc_attr( $class ), $disabled_text, $placeholder_attribute, $required_attribute, $invalid_attribute, $aria_describedby, $autocomplete_attribute, $instruction );
return $input;
}
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', true, $this );
return GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ), $include_thousands_sep );
}
/**
* Format the entry value for display on the entry detail page and for the {all_fields} merge tag.
*
* @since 1.9
* @since 2.9.29 Changed the second parameter $currency (string) to $entry (array).
*
* @param string|array $value The field value.
* @param array $entry The entry.
* @param bool|false $use_text When processing choice based fields should the choice text be returned instead of the value.
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
* @param string $media The location where the value will be displayed. Possible values: screen or email.
*
* @return string
*/
public function get_value_entry_detail( $value, $entry = array(), $use_text = false, $format = 'html', $media = 'screen' ) {
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', $use_text, $this );
return GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ), $include_thousands_sep );
}
/**
* Gets merge tag values.
*
* @since Unknown
* @access public
*
* @uses GFCommon::format_number()
*
* @param array|string $value The value of the input.
* @param string $input_id The input ID to use.
* @param array $entry The Entry Object.
* @param array $form The Form Object
* @param string $modifier The modifier passed.
* @param array|string $raw_value The raw value of the input.
* @param bool $url_encode If the result should be URL encoded.
* @param bool $esc_html If the HTML should be escaped.
* @param string $format The format that the value should be.
* @param bool $nl2br If the nl2br function should be used.
*
* @return string The processed merge tag.
*/
public function get_value_merge_tag( $value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br ) {
$include_thousands_sep = ! in_array( 'value', $this->get_modifiers() );
/**
* Filters if the thousands separator should be used when displaying the a number field result.
*
* @since 1.9.5
*
* @param bool $include_thousands_sep If the modifier passed in the merge tag is not 'value', false. Otherwise, true.
* @param GF_Field_Number $this An instance of this class.
*/
$include_thousands_sep = apply_filters( 'gform_include_thousands_sep_pre_format_number', $include_thousands_sep, $this );
$formatted_value = GFCommon::format_number( $value, $this->numberFormat, rgar( $entry, 'currency' ), $include_thousands_sep );
return $url_encode ? urlencode( $formatted_value ) : $formatted_value;
}
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
if ( $this->has_calculation() ) {
if ( empty( $lead ) ) {
$lead = GFFormsModel::get_lead( $lead_id );
}
$value = GFCommon::calculate( $this, $form, $lead );
if ( $this->numberFormat !== 'currency' ) {
$value = GFCommon::round_number( $value, $this->calculationRounding );
}
// Return the value as a string when it is zero and a calc so that the "==" comparison done when checking if the field has changed isn't treated as false.
if ( $value == 0 ) {
$value = '0';
}
} else {
$value = $this->clean_number( GFCommon::maybe_add_leading_zero( $value ) );
}
return $this->sanitize_entry_value( $value, $form['id'] );
}
public function sanitize_settings() {
parent::sanitize_settings();
$this->enableCalculation = (bool) $this->enableCalculation;
if ( ! in_array( $this->numberFormat, array( 'currency', 'decimal_comma', 'decimal_dot' ) ) ) {
$this->numberFormat = GFCommon::is_currency_decimal_dot() ? 'decimal_dot' : 'decimal_comma';
}
$this->rangeMin = $this->clean_number( $this->rangeMin );
$this->rangeMax = $this->clean_number( $this->rangeMax );
if ( $this->numberFormat == 'decimal_comma' ) {
$this->rangeMin = GFCommon::format_number( $this->rangeMin, 'decimal_comma' );
$this->rangeMax = GFCommon::format_number( $this->rangeMax, 'decimal_comma' );
}
}
public function clean_number( $value ) {
if ( $this->numberFormat == 'currency' ) {
return GFCommon::to_number( $value );
} else {
return GFCommon::clean_number( $value, $this->numberFormat );
}
}
}
GF_Fields::register( new GF_Field_Number() );
namespace Gravity_Forms\Gravity_Forms\Orders\Summaries;
use \Gravity_Forms\Gravity_Forms\Orders\GF_Order;
use \Gravity_Forms\Gravity_Forms\Orders\Factories\GF_Order_Factory;
use \Gravity_Forms\Gravity_Forms\Orders\Exporters\GF_Entry_Details_Order_Exporter;
final class GF_Order_Summary {
/**
* Contains any specific configurations for rendering the summary, for example showing only a receipt.
*
* @since 2.6
*
* @var array
*/
public static $configurations;
/**
* Renders the summary markup using the provided data and view.
*
* @since 2.6
*
* @param array $form The form object.
* @param array $entry The entry object.
* @param string $view The view to be used for rendering the order.
* @param bool $use_choice_text If the product field has choices, this decided if the choice text should be retrieved along with the product name or not.
* @param bool $use_admin_labels Whether to use the product admin label or the front end label.
* @param bool $receipt Whether to show only the line items paid for in the order or all products in the form.
*
* @return string The summary markup.
*/
public static function render( $form, $entry, $view = 'order-summary', $use_choice_text = false, $use_admin_labels = false, $receipt = false ) {
GF_Order_Factory::load_dependencies();
$order = GF_Order_Factory::create_from_entry( $form, $entry, $use_choice_text, $use_admin_labels, rgar( self::$configurations, 'receipt' ) );
$order_summary = ( new GF_Entry_Details_Order_Exporter( $order ) )->export();
if ( empty( $order_summary['rows'] ) ) {
return '';
}
$order_summary['labels'] = self::get_labels( $form );
ob_start();
include 'views/view-' . $view . '.php'; // nosemgrep audit.php.lang.security.file.inclusion-arg
return ob_get_clean();
}
/**
* Return the labels used in the summary view.
*
* @since 2.6
*
* @param array form The form object.
*
* @return array
*/
public static function get_labels( $form ) {
return array(
'order_label' => gf_apply_filters( array( 'gform_order_label', $form['id'] ), __( 'Order', 'gravityforms' ), $form['id'] ),
'product' => gf_apply_filters( array( 'gform_product', $form['id'] ), __( 'Product', 'gravityforms' ), $form['id'] ),
'product_qty' => gf_apply_filters( array( 'gform_product_qty', $form['id'] ), __( 'Qty', 'gravityforms' ), $form['id'] ),
'product_unitprice' => gf_apply_filters( array( 'gform_product_unitprice', $form['id'] ), __( 'Unit Price', 'gravityforms' ), $form['id'] ),
'product_price' => gf_apply_filters( array( 'gform_product_price', $form['id'] ), __( 'Price', 'gravityforms' ), $form['id'] ),
);
}
}
namespace Gravity_Forms\Gravity_Forms\Settings\Fields;
use Gravity_Forms\Gravity_Forms\Settings\Fields;
defined( 'ABSPATH' ) || die();
// Load base classes.
require_once 'class-checkbox.php';
require_once 'class-select.php';
class Checkbox_And_Select extends Base {
/**
* Field type.
*
* @since 2.5
*
* @var string
*/
public $type = 'checkbox_and_select';
/**
* Child inputs.
*
* @since 2.5
*
* @var Base[]
*/
public $inputs = array();
/**
* Initialize Checkbox and Select field.
*
* @since 2.5
*
* @param array $props Field properties.
* @param \Gravity_Forms\Gravity_Forms\Settings\Settings $settings Settings instance.
*/
public function __construct( $props, $settings ) {
parent::__construct( $props, $settings );
// Prepare Checkbox field.
$checkbox_input = rgars( $props, 'checkbox' );
$checkbox_field = array(
'type' => 'checkbox',
'name' => rgar( $props, 'name' ) . 'Enable',
'label' => esc_html__( 'Enable', 'gravityforms' ),
'horizontal' => true,
'value' => '1',
'choices' => false,
'tooltip' => false,
);
$this->inputs['checkbox'] = wp_parse_args( $checkbox_input, $checkbox_field );
$this->inputs['checkbox'] = Fields::create( $this->inputs['checkbox'], $this->settings );
// Prepare Select field.
$select_input = rgars( $props, 'select' );
$select_field = array(
'name' => rgar( $props, 'name' ) . 'Value',
'type' => 'select',
'class' => '',
'tooltip' => false,
'disabled' => $this->inputs['checkbox']->get_value() ? false : true,
);
$select_field['class'] .= ' ' . $select_field['name'];
$this->inputs['select'] = wp_parse_args( $select_input, $select_field );
// Add on change event to Checkbox.
if ( empty( $this->inputs['checkbox']['choices'] ) ) {
$this->inputs['checkbox']['choices'] = array(
array(
'name' => $this->inputs['checkbox']['name'],
'label' => $this->inputs['checkbox']['label'],
'onchange' => sprintf(
"( function( $, elem ) {
$( elem ).parents( 'td' ).css( 'position', 'relative' );
if( $( elem ).prop( 'checked' ) ) {
$( '%1\$s' ).prop( 'disabled', false );
} else {
$( '%1\$s' ).prop( 'disabled', true );
}
} )( jQuery, this );",
"#{$this->inputs['select']['name']}Span select" ),
),
);
}
$this->inputs['select'] = Fields::create( $this->inputs['select'], $this->settings );
}
// # RENDER METHODS ------------------------------------------------------------------------------------------------
/**
* Render field.
*
* @since 2.5
*
* @return string
*/
public function markup() {
// Prepare markup.
// Display description.
$html = $this->get_description();
// Settings are more up-to-date at this point; set the disabled attr on the select based on checkbox state.
$this->inputs['select']->disabled = ! $this->inputs['checkbox']->get_value();
$html .= sprintf(
'%s %s %s ',
esc_attr( $this->get_container_classes() ),
$this->inputs['checkbox']->markup(),
$this->inputs['select']->name . 'Span',
$this->inputs['select']->markup(),
$this->settings->maybe_get_tooltip( $this->inputs['select'] )
);
$html .= $this->get_error_icon();
return $html;
}
/**
* Get the correctly-grouped values from $_POST for use in validation.
*
* @since 2.5
*
* @param array $values The $_POST values.
*
* @return array
*/
public function get_values_from_post( $values ) {
$return_values = array();
$cb_name = $this->inputs['checkbox']->name;
$select_name = $this->inputs['select']->name;
if ( isset( $values[ $cb_name ] ) ) {
$return_values['checkbox'] = $values[ $cb_name ];
}
if ( isset( $values[ $select_name ] ) ) {
$return_values['select'] = $values[ $select_name ];
}
return $return_values;
}
/**
* Filter out unneeded select values when the checkbox isn't checked.
*
* @since 2.5
*
* @param array $field_values Posted field values.
* @param array|bool|string $field_value Posted value for field.
*
* @return array
*/
public function save_field( $field_values, $field_value ) {
$field_values = parent::save_field( $field_values, $field_value );
$cb_value = isset( $field_values[ $this->inputs['checkbox']->name ] ) ? $field_values[ $this->inputs['checkbox']->name ] : 0;
// Checkbox is unchecked, remove the select value.
if ( $cb_value == 0 ) {
unset( $field_values[ $this->inputs['select']->name ] );
}
return $field_values;
}
// # VALIDATION METHODS --------------------------------------------------------------------------------------------
/**
* Validate posted field value.
*
* @since 2.5-beta-3
*
* @param array $values Posted field values.
*/
public function do_validation( $values ) {
$cb_value = isset( $values['checkbox'] ) ? $values['checkbox'] : null;
$select_value = isset( $values['select'] ) ? $values['select'] : null;
if ( ! isset( $cb_value[0] ) || $cb_value[0] != 1 ) {
return;
}
if ( isset( $cb_value[0] ) && $cb_value[0] == 1 ) {
$this->inputs['select']->required = true;
}
$this->inputs['checkbox']->handle_validation( $cb_value );
$this->inputs['select']->handle_validation( $select_value );
}
}
Fields::register( 'checkbox_and_select', '\Gravity_Forms\Gravity_Forms\Settings\Fields\Checkbox_and_Select' );
(()=>{"use strict";const e=(()=>{const e={},t={},r={};return{registerPortal(r,s){e[r]={element:s,isReady:!0},t[r]&&t[r].forEach(e=>e(s))},unregisterPortal(t){e[t]&&delete e[t],r[t]&&(r[t].forEach(e=>e()),delete r[t])},onReady(r,s){e[r]?.isReady?s(e[r].element):(t[r]=t[r]||[],t[r].push(s))},onRemoved(e,t){r[e]=r[e]||[],r[e].push(t)},isReady:t=>!!e[t]?.isReady,getElement:t=>e[t]?.element||null}})();window.NFDPortalRegistry=e})();
University News | UAMS News
Skip to main content
University News
May 8, 2023 | LITTLE ROCK —A number of dignitaries and other visitors gathered today to celebrate the opening of The Orthopaedic & Spine Hospital at the University of Arkansas for Medical Sciences (UAMS).
May 8, 2023 | Students in the Occupational Therapy Doctoral (OTD) program recently held their second annual OT Olympics on the University of Arkansas for Medical Sciences (UAMS) Northwest Regional Campus to celebrate Occupational Therapy (OT) Month in April. Students and faculty from every program at UAMS in Northwest Arkansas were invited to compete in different assessments common to...
May 5, 2023 | The University of Arkansas for Medical Sciences (UAMS) hosted experts from the field of otolaryngology for a two-day conference that offered the latest in surgical techniques, clinical care and research. The third annual Otolaryngology Diamond Conference extended its focus beyond the ear, nose and throat specialty by welcoming health professionals from a variety of treatment...
May 4, 2023 | The University of Arkansas for Medical Sciences (UAMS) Arkansas Center for Health Disparities (ARCHD) held a two-day conference in North Little Rock for its community partners and individuals from throughout the state. The center, which is part of the UAMS Fay W. Boozman College of Public Health Department of Health Behavior and Health Education, created...
May 3, 2023 | Ten students represented the University of Arkansas for Medical Sciences (UAMS) chapter of the Student National Pharmaceutical Association at a regional conference that gave them the opportunity to network with peers, pharmacists and potential employers. The conference, held March 31-April 1 in New Orleans, included pharmacy students from the organization’s West Coast, Midwest and Southwest...
May 2, 2023 | FAYETTEVILLE — Rural women cancer survivors are more likely to experience financial strain related to basic household needs rather than medical debt, according to researchers from the University of Arkansas for Medical Sciences (UAMS) Office of Community Health & Research. The study, “It was kind of a nightmare, it really was:” Financial Toxicity Among Rural...
May 2, 2023 | LITTLE ROCK — Christi Madden, MPA, has joined the UAMS Translational Research Institute as its executive director. Madden, a leader with more than two decades of research programmatic management experience, spent most of her career in her home state of Oklahoma at the University of Oklahoma Health Sciences Center (OUHSC), where she worked in the...
May 1, 2023 | LITTLE ROCK — A groundbreaking nationwide clinical trial in which the University of Arkansas for Medical Sciences (UAMS) played a key role has confirmed an effective way to wean newborns from opioid withdrawal symptoms that substantially reduces hospital stays and the traditional use of drug therapies. Using an “Eat, Sleep, Console” (ESC) care approach resulted...
April 28, 2023 | Health professionals in the United States have an important role to play in the climate crisis because it is also a public health crisis, Victor J. Dzau, M.D., president of the National Academy of Medicine, told an audience at the University of Arkansas for Medical Sciences (UAMS). As the inaugural lecturer for The Richard and...
April 28, 2023 | Cataracts had made life so difficult for Joshua Roby, 43, of Springdale that he could not write up reports at his security job, and he needed help walking around. Less than a day after cataract surgery, he says his vision is “much, much better,” and he can move well on his own. Eight patients from...
Previous page Next page