diff -urpN flickr/field/flickrfield.info flickr/field/flickrfield.info --- flickr/field/flickrfield.info 2008-03-24 15:56:09.000000000 -0400 +++ flickr/field/flickrfield.info 2009-08-20 14:06:20.000000000 -0400 @@ -1,7 +1,8 @@ ; $Id: flickrfield.info,v 1.3 2008/03/24 19:56:09 drewish Exp $ name = Flickrfield -description = Flickr CCK field to insert Flickr images into content. +description = Flickr CCK field to insert Flickr images into content. Note: also depends on wimleers' this patch from #336517 ( http://drupal.org/node/336517 ) dependencies[] = flickr dependencies[] = content +dependencies[] = ahah_helper package = CCK core = 6.x diff -urpN flickr/field/flickrfield.module flickr/field/flickrfield.module --- flickr/field/flickrfield.module 2009-06-24 15:25:34.000000000 -0400 +++ flickr/field/flickrfield.module 2009-08-20 14:37:34.000000000 -0400 @@ -8,6 +8,12 @@ * @todo - think about how to control access to photos, might be tricky because of CCK caching. */ +define('FLICKRFIELD_DEFAULT_PHOTOS_PER_PAGE', 20); +define('FLICKRFIELD_FLICKR_ID_CSS_CLASS', 'flickrfield-flickr-id'); +define('FLICKRFIELD_FLICKR_TYPE_CSS_CLASS', 'flickrfield-flickr-type'); +define('FLICKRFIELD_FLICKR_BROWSER_WRAPPER_CSS_CLASS', 'wrappr-wrappr'); +define('FLICKRFIELD_FLICKR_BROWSER_IMAGE_CSS_CLASS_PREFIX', 'flickr-asset-id-'); + /** * Include css unconditionally. */ @@ -102,10 +108,40 @@ function flickrfield_elements() { ); } +function flickrfield_widget_settings($op, $widget) { + switch ($op) { + case 'form': + $form = array(); + $mode = isset($widget['flickrfield_show_browser']) ? $widget['flickrfield_show_browser'] : FALSE; + $form['flickrfield_show_browser'] = array( + '#type' => 'checkbox', + '#title' => t('Show Flickr Browser?'), + '#default_value' => $mode, + '#description' => t('Checking this box enables flickr browser, a widget that allows you to page through all your photos and photosets to select one, rather than entering the flickr id by hand.'), + ); + return $form; + + case 'save': + return array('flickrfield_show_browser'); + } +} + function flickrfield_widget(&$form, &$form_state, $field, $items, $delta = 0) { + $default_value = isset($items[$delta]) ? $items[$delta] : ''; + + if(!empty($field['widget']['flickrfield_show_browser'])) { + ahah_helper_register($form, $form_state); + // ahah_helper uses $form_state['storage'] to keep track of form data across ahah submissions. + if (isset($form_state['storage'][$field['field_name']][$delta])) { + $default_value = $form_state['storage'][$field['field_name']][$delta]; + } + } + $element = array( '#type' => $field['widget']['type'], - '#default_value' => isset($items[$delta]) ? $items[$delta] : '', + '#default_value' => $default_value, + // Set a dummy element to enable rendering of the flickr browser. + 'browser' => array('#type' => 'value', '#value' => !empty($field['widget']['flickrfield_show_browser'])) ); return $element; } @@ -119,11 +155,13 @@ function flickrfield_process($element, $ '#title' => t('Item Type'), '#default_value' => !empty($element['#value']['type']) ? $element['#value']['type'] : '', '#options' => $options, + '#attributes' => array('class' => FLICKRFIELD_FLICKR_TYPE_CSS_CLASS), ); $element['id'] = array( '#type' => 'textfield', '#title' => t('Id'), '#default_value' => !empty($element['#value']['id']) ? $element['#value']['id'] : '', + '#attributes' => array('class' => FLICKRFIELD_FLICKR_ID_CSS_CLASS), ); $element['nsid'] = array( '#type' => 'textfield', @@ -132,6 +170,14 @@ function flickrfield_process($element, $ '#required' => $element['#required'], '#description' => t("The user id of the Flickr user who owns the photos. If this is left blank, the sites's default user will be used. Current default id is @id.", array('@id' => variable_get('flickr_default_userid', ''))), ); + + if($element['browser']['#value']) { + // Rather than set an arbitrarily large weight, unset and re-set the + // dummy element to re-position the browser below the rest of the field. + unset($element['browser']); + $element['browser'] = _flickrfield_attach_browser($element, $edit, $form_state, $form, $page); + $element['#theme'][] = 'flickrfield_browser_wrapper'; + } return $element; } @@ -155,7 +201,7 @@ function flickrfield_flickrid_process($e */ function flickrfield_content_is_empty($item, $field) { if ($field['type'] == 'flickrfield') { - return empty($item['id']); + return empty($item['id']); } else if ($field['type'] == 'flickrfield_photoset') { return empty($item['flickrid']); } @@ -165,7 +211,7 @@ function flickrfield_content_is_empty($i * Implementation of hook_field_formatter_info(). */ function flickrfield_field_formatter_info() { - require_once(drupal_get_path('module', 'flickr') .'/flickr.inc'); + require_once(drupal_get_path('module', 'flickr') . '/flickr.inc'); $sizes = flickr_photo_sizes(); // Formatters for general Flickr CCK field. foreach ($sizes as $size => $info) { @@ -204,7 +250,7 @@ function flickrfield_field_formatter_inf * Implementation of hook_theme(). */ function flickrfield_theme() { - require_once(drupal_get_path('module', 'flickr') .'/flickr.inc'); + require_once(drupal_get_path('module', 'flickr') . '/flickr.inc'); $themes = array(); foreach (flickr_photo_sizes() as $size => $info) { $themes['flickrfield_formatter_'. $size] = array( @@ -212,15 +258,15 @@ function flickrfield_theme() { 'function' => 'theme_flickrfield_field_formatter', ); // Theme function for the primary photo formatters of a Flickr photo set. - $themes['flickrfield_formatter_photoset_primaryphoto_size'. $size .'_nolink'] = array( + $themes['flickrfield_formatter_photoset_primaryphoto_size' . $size . '_nolink'] = array( 'arguments' => array('element'), 'function' => 'theme_flickrfield_formatter_photoset_primaryphoto', ); - $themes['flickrfield_formatter_photoset_primaryphoto_size'. $size .'_linknode'] = array( + $themes['flickrfield_formatter_photoset_primaryphoto_size' . $size . '_linknode'] = array( 'arguments' => array('element'), 'function' => 'theme_flickrfield_formatter_photoset_primaryphoto', ); - $themes['flickrfield_formatter_photoset_primaryphoto_size'. $size .'_linkflickrcomset'] = array( + $themes['flickrfield_formatter_photoset_primaryphoto_size' . $size . '_linkflickrcomset'] = array( 'arguments' => array('element'), 'function' => 'theme_flickrfield_formatter_photoset_primaryphoto', ); @@ -247,6 +293,12 @@ function flickrfield_theme() { 'flickrfield_formatter_photoset_flickrcomsetlink' => array( 'arguments' => array('element'), ), + 'flickrfield_browser' => array( + 'arguments' => array('element'), + ), + 'flickrfield_browser_wrapper' => array( + 'arguments' => array('element'), + ), ); } @@ -254,7 +306,7 @@ function flickrfield_theme() { * Basic flickrfield formatter. */ function theme_flickrfield_field_formatter($element) { - require_once(drupal_get_path('module', 'flickr') .'/flickr.inc'); + require_once(drupal_get_path('module', 'flickr') . '/flickr.inc'); $item = $element['#item']; if (empty($item['id'])) { return; @@ -280,7 +332,7 @@ function theme_flickrfield_field_formatt * Theme a Flickr photo set as the primary photo of that set. */ function theme_flickrfield_formatter_photoset_primaryphoto($element) { - require_once(drupal_get_path('module', 'flickr') .'/flickr.inc'); + require_once(drupal_get_path('module', 'flickr') . '/flickr.inc'); if (empty($element['#item']['flickrid'])) { return; } @@ -291,7 +343,7 @@ function theme_flickrfield_formatter_pho $img = flickr_img($set_data, $size); switch ($formatter_info[3]) { case 'linknode': - $link = 'node/'. $element['#node']->nid; + $link = 'node/' . $element['#node']->nid; break; case 'linkflickrcomset': $link = $set_url; @@ -309,7 +361,7 @@ function theme_flickrfield_formatter_pho * Theme a Flickr photo set as an embedded Flickr.com flash slideshow. */ function theme_flickrfield_formatter_photoset_flickrcomslideshow($element) { - require_once(drupal_get_path('module', 'flickr') .'/flickr.inc'); + require_once(drupal_get_path('module', 'flickr') . '/flickr.inc'); if (empty($element['#item']['flickrid'])) { return; } @@ -339,24 +391,24 @@ function theme_flickrfield_formatter_pho function theme_flickrfield_photo($img, $photo_url, $formatter, $photo_data, $node) { $title = is_array($photo_data['title']) ? $photo_data['title']['_content'] : $photo_data['title']; if (arg(0) == 'node' && arg(1) == $node->nid) { - $output = '
'. $img .'
'; + $output = '
' . $img . '
'; } else { - $output = '
'. l($img, 'node/'. $node->nid, array('attributes' => array('title' => $title), 'absolute' => TRUE, 'html' => TRUE)) . '
'; + $output = '
' . l($img, 'node/' . $node->nid, array('attributes' => array('title' => $title), 'absolute' => TRUE, 'html' => TRUE)) . '
'; } - $output .= '
'. l(t('Source: Flickr'), $photo_url) .'
'; + $output .= '
' . l(t('Source: Flickr'), $photo_url) . '
'; return $output; } function theme_flickrfield_photoset($img, $photo_url, $formatter, $photo_data, $node) { $title = is_array($photo_data['title']) ? $photo_data['title']['_content'] : $photo_data['title']; if (arg(0) == 'node' && arg(1) == $node->nid) { - $output = '
'. $img .'
'; + $output = '
' . $img . '
'; } else { - $output = '
'. l($img, 'node/'. $node->nid, array('attributes' => array('title' => $title), 'absolute' => TRUE, 'html' => TRUE)) . '
'; + $output = '
' . l($img, 'node/' . $node->nid, array('attributes' => array('title' => $title), 'absolute' => TRUE, 'html' => TRUE)) . '
'; } - $output .= '
'. l(t('Source: Flickr'), $photo_url) .'
'; + $output .= '
' . l(t('Source: Flickr'), $photo_url) . '
'; return $output; } @@ -372,18 +424,18 @@ function theme_flickrfield_photoset($img */ function theme_flickrfield_photoset_primaryphoto($img, $link, $set_url, $size, $title) { if ($link) { - $output = '
'. l($img, $link, array('attributes' => array('title' => $title), 'html' => TRUE)) . '
'; + $output = '
' . l($img, $link, array('attributes' => array('title' => $title), 'html' => TRUE)) . '
'; } else { - $output = '
'. $img .'
'; + $output = '
' . $img . '
'; } - $output .= '
'. l(t('Source: Flickr'), $set_url) .'
'; + $output .= '
' . l(t('Source: Flickr'), $set_url) . '
'; return $output; } /** * Theme for the form element. - * + * * The form is already rendered by the child elements by the time it comes back here, * just group each delta grouping into its own fieldset. */ @@ -391,13 +443,14 @@ function theme_flickrfield($element) { $fields = content_fields(); $field = $fields[$element['#field_name']]; $fieldset = array( - '#title' => $field['widget']['label'] .' '. ($element['#delta'] > 0 ? intval($element['#delta'] + 1) : ''), + '#title' => $field['widget']['label'] . ' ' . ($element['#delta'] > 0 ? intval($element['#delta'] + 1) : ''), '#value' => $element['#children'], '#collapsible' => FALSE, '#collapsed' => FALSE, '#description' => $element['#description'], '#attributes' => array(), ); + return theme('fieldset', $fieldset); } @@ -410,3 +463,387 @@ function theme_flickrfield($element) { function theme_flickrfield_flickrid($element) { return $element['#children']; } + +/** + * Flickrfield browser displays a list of flickr images, based on the + * flickrfield's nsid, as well as a ahah-based flickr pager to look through + * the images. The included javascript allows a user to select an image by + * clicking on it, which populates the flickrfield's Id textfield. + * + * Parameters are passed as-is from the #process callback for hook_elements + * + * TODO: photos and photosets should be abstracted to "assets" and assets + * should be looped, instead of doing everything twice. What happens when we + * want to use flickr video? + * + * @param string $element + * @param string $edit + * @param string $form_state + * @param string $form + * @return Flickr image browser in FAPI format + * @see flickrfield_process + */ +function _flickrfield_attach_browser($element, $edit, $form_state, $form) { + drupal_add_js(drupal_get_path('module', 'flickrfield') . '/misc/flickrfield.js'); + drupal_add_css(drupal_get_path('module', 'flickrfield') . '/misc/flickrfield.css'); + $nsid = $element['#value']['nsid'] ? $element['#value']['nsid'] : variable_get('flickr_default_userid', ''); + $pickr = array(); + + // TODO: allow node admins to specify only photos, only photosets, or both. + $photos_position = $photos_page = + _flickrfield_get_page('photos', $element, $form_state); + $photosets_position = $photosets_page = + _flickrfield_get_page('photosets', $element, $form_state); + + // TODO: allow node admins to manage flickr images per page via cck settings. + $per_page = variable_get('flickr_photos_per_page', FLICKRFIELD_DEFAULT_PHOTOS_PER_PAGE); + if(!empty($nsid)) { + $photos = flickr_photos_search($nsid, $photos_page, array('per_page' => $per_page)); + $photosets = flickr_photoset_get_list($nsid); + $total = count($photosets); + // Flickr doesn't support paging for photosets, so we do it here manually. + if($total > $per_page) { + $photosets = array_slice($photosets, ($photosets_page - 1) * $per_page, $per_page); + } + $photosets = array('photo' => $photosets, 'page' => $photosets_page, + 'pages' => ceil($total / $per_page), + 'total' => $total, 'perpage' => $per_page); + } + + // If fetching photos failed, or we don't have a flickr user id, grab some random recent panda photos. + if(empty($photos)) { + $pandas = TRUE; + $photos = flickrfield_get_random_panda_photos(); + } + + // OK, give up now. + if (empty($photos)) { + return array('error' => array('#type' => 'markup', '#value' => t('No accessible photos found for Flickr %userid', array('%userid' => $nsid)))); + } + + $name = null; + foreach($element['#parents'] as $el) { + if(empty($name)) { $name = $el; } + else { $name .= '[' . $el . ']'; } + } + $pickr += array( + 'photos' => array( + 'page' => array('#type' => 'value', '#value' => $photos_page), + 'position' => array('#type' => 'value', '#value' => $photos_position), + 'photos' => array('#type' => 'value', '#value' => $photos), + '#title' => t('Photos'), + '#type' => 'markup', + '#theme' => 'flickrfield_browser', + ), + 'photosets' => array( + 'page' => array('#type' => 'value', '#value' => $photosets_page), + 'position' => array('#type' => 'value', '#value' => $photosets_position), + 'photosets' => array('#type' => 'value', '#value' => $photosets), + '#title' => t('Photosets'), + '#type' => 'markup', + '#theme' => 'flickrfield_browser', + ), + ); + + // No paging for pandas, sorry. + if(!$pandas) { + // TODO: this is fugly. Clean it up. + $name = null; + foreach($element['#parents'] as $el) { + if(empty($name)) { + $name = $el; + } + else { + $name .= '[' . $el . ']'; + } + } + $callback_element = $element['#parents']; + $callback_element[] = 'browser'; + $photos_wrapper = implode('-', $callback_element) . '-photos-flickr-wrappr'; + $photosets_wrapper = implode('-', $callback_element) . '-photosets-flickr-wrappr'; + $photos_name = $name . '[photos][page]'; + $photosets_name = $name . '[photosets][page]'; + $photos_path = ahah_helper_path(array_merge($callback_element, array('photos'))); + $photosets_path = ahah_helper_path(array_merge($callback_element, array('photosets'))); + $pickr['photos']['pager'] = _flickrfield_browser_pagers($photos, $photos_wrapper, $photos_name, $photos_path); + $pickr['photosets']['pager'] = _flickrfield_browser_pagers($photosets, $photosets_wrapper, $photosets_name, $photosets_path); + $pickr['photos']['wrapper'] = array('#type' => 'value', '#value' => $photos_wrapper); + $pickr['photosets']['wrapper'] = array('#type' => 'value', '#value' => $photosets_wrapper); + if(isset($form_state['values'][$element['#field_name']][$element['#delta']]['photos']['target'])) { + $target = $form_state['values'][$element['#field_name']][$element['#delta']]['photos']['target']; + } + elseif($form_state['storage'][$element['#field_name']][$element['#delta']]['photos']['target']) { + $target = $form_state['storage'][$element['#field_name']][$element['#delta']]['photos']['target']; + } + else { + $target = null; + } + + // Target is the dom id of this flickrfield's flickr id textfield (flickrid). + // On the form build, flickrid's dom id will not be set until the theming + // layer takes over, so we set the value to null unless we were posted to. + // Since the flickrid will not get rebuilt on an ahah submit, we have to use + // a hidden field to store this value, or we'll lose it altogether on an + // ahah-built form. + $pickr['photos']['target'] = array('#type' => 'hidden', '#value' => $target, '#name' => $name . '[photos][target]'); + $pickr['photosets']['target'] = array('#type' => 'hidden', '#value' => $target, '#name' => $name . '[photosets][target]'); + } + + return $pickr; +} + +/** + * Internal function to get the current position of the pager corresponding to a type/element pair + * + * @param string $type asset type: "photos" or "photosets" + * @param array $element the flickrfield FAPI element + * @param array $form_state the current FAPI values, either ahah-posted or initialized + * @return the numeric page number + * @see _flickrfield_browser_pagers, http://drupal.org/project/ahah_helper + */ +function _flickrfield_get_page($type, $element, $form_state) { + $name = $element['#field_name']; + $delta = $element['#delta']; + // If there's been an ahah postback, ahah_helper will populate + // form_state['values'] with the ahah-posted data, or form_state['storage'] + // will contain the last-known value for the field. + // See ahah_helper.module for more info. + if(isset($form_state['values'][$name][$delta][$type])) { + $page = $form_state['values'][$name][$delta][$type]['page']; + } + elseif(isset($form_state['storage'][$name][$delta][$type])) { + $page = $form_state['storage'][$name][$delta][$type]['page']; + } + else { + // If we found nothing, then we're done here. + return 1; + } + + $position = isset($form_state['storage'][$name][$delta][$type]['position']) + ? $form_state['storage'][$name][$delta][$type]['position'] + : 1; + + // Validate and reset the page number if necessary. + if(empty($page) || !is_numeric($page)) { + switch($page) { + case t('< Prev'): + $page = $position - 1; + break; + case t('Next >'): + $page = $position + 1; + break; + default: + $page = isset($element['browser'][$type]['position']['#value']) ? $element['browser'][$type]['position']['#value'] : 1; + break; + } + if(empty($page) || !is_numeric($page)) { + $page = 1; + } + } + return $page; +} + +/** + * Internal function to generate pagers for an asset set, mimicking flickr.com + * @see _flickrfield_browser_pagers + */ +function _flickrfield_browser_pagers($photos, $wrapper, $name, $path) { + $n_pages = $photos['pages']; + $cur_page = $photos['page']; + $total_pages = ceil($photos['total'] / ($photos['perpage'] ? $photos['perpage'] : variable_get('flickr_photos_per_page', FLICKRFIELD_DEFAULT_PHOTOS_PER_PAGE))); + $items = $upper_range = $lower_range = array(); + if($total_pages <= 1) { + return FALSE; + } + + // Flickr's pager behaves quite differently than Drupal's. This elaborate + // logic is as elegantly as I can figure out how to mimic flickr.com's pager. + if($cur_page != 1) { + $items[0] = array('#value' => t('< Prev')); + } + switch(TRUE) { + case $total_pages < 18: + foreach(range(1, $total_pages) as $i) { + $items[$i] = $i; + } + break; + case $cur_page < 9: + $upper = ($cur_page + 3 > 7) ? ($cur_page + 3) : 7; + foreach(range(1, $upper) as $i) { + $items[$i] = $i; + } + $upper_range = array($total_pages - 1, $total_pages); + break; + case $cur_page > $total_pages - 9: + $lower_range = array(1, 2); + $lower = $cur_page - 3 < $total_pages - 7 ? $cur_page - 3 : $total_pages - 7; + foreach(range($lower, $total_pages) as $i) { + $items[$i] = $i; + } + break; + default: + $lower_range = array(1, 2); + foreach(range($cur_page - 3 , $cur_page + 3) as $i) { + $items[$i] = $i; + } + $upper_range = array($total_pages - 1, $total_pages); + break; + } + + if($cur_page != $total_pages) { + $items[$total_pages + 1] = array('#value' => t('Next >')); + } + + foreach(array_merge($lower_range, $upper_range) as $i) { + $items[$i] = $i; + } + + $last = 0; + $final_items = array(); + ksort($items); + + $default_button = array( + '#name' => $name, '#type' => 'button', + '#submit' => array('ahah_helper_submit'), + '#ahah' => array('method' => 'replace', 'event' => 'click', + 'wrapper' => $wrapper, 'path' => $path)); + + foreach($items as $i => $button) { + if($last < $i - 1) { + $final_items[$last+1] = array( + '#weight' => $last + 1, + '#type' => 'markup', + '#value' => '...'); + } + if($cur_page == $i) { + $final_items[$i] = array( + '#type' => 'markup', + '#value' => '' . $i . '', + '#weight' => $i); + } + else { + $final_button = $default_button + array('#weight' => $i, '#value' => is_numeric($button) ? $button : $button['#value']); + $final_items[$i] = $final_button; + } + $last = $i; + } + // Set the wrapper as a form value for easy access in the theming function. + + // Even if there's not gonna be a pager, we still need a wrapper for the theming function. + if(count($final_items) <= 1) { return FALSE; } + return $final_items; +} + +/** + * Theme the browser: list of photos, pagers, and hidden flickrfield id field + * + * @param array $element FAPI element containing an asset set + * (photos or photosets, not the entire flickrfield) + * @return the rendered browser + * @see _flickrfield_attach_browser + */ +function theme_flickrfield_browser($element) { + static $link_class; + if(!$link_class) { + $link_class = 'flickr-pickr-imagelink'; + $settings = array('imglinkclass' => $link_class); + drupal_add_js(array('flickrpickr' => $settings), 'setting'); + } + + if(isset($element['photos'])) { + $type = 'photos'; + } elseif(isset($element['photosets'])) { + $type = 'photosets'; + } else { + return; + } + $photos = $element[$type]['#value']; + + // TODO: allow node admins to specify default browser image size. + $size = 's'; + $items = array(); + foreach($photos['photo'] as $i=>$photo) { + $pid = $photo['id']; + $attr = array('id' => $element['target']['#value'] . '-' . $pid); + $image = flickr_img($photo, $size, $attr); + $items[] = '
' . $image . '
'; + } + + $browser = array('#type' => 'markup', '#value' => + '
' + . '' + . '
' + . theme_item_list($items) + . '
' + . '
' + . drupal_render($element['pager']) + . '
' + . drupal_render($element['target']) + . '
'); + return drupal_render($browser); +} + +/** + * Wrap the flickr browser, attach javascript settings, and set the + * flickrfield id target for asset selection. + * + * @param array $element the flickrfield + * @return the rendered flickrfield element + * @see flickrfield_process + */ +function theme_flickrfield_browser_wrapper($element) { + static $setting; + if(empty($setting)) { + $setting = array( + 'flickrimgprefix' => FLICKRFIELD_FLICKR_BROWSER_IMAGE_CSS_CLASS_PREFIX, + 'flickridfield' => FLICKRFIELD_FLICKR_ID_CSS_CLASS, + 'flickrtypefield' => FLICKRFIELD_FLICKR_TYPE_CSS_CLASS, + 'flickrbrowserwrapper' => FLICKRFIELD_FLICKR_BROWSER_WRAPPER_CSS_CLASS + ); + drupal_add_js(array('flickrpickr' => $setting), 'setting'); + } + + // To avoid clutter on the node form, the browser is hidden by default. + // Assign a css class equivalent to the flickr id textfield, so that when the + // textfield is focused, the browser appears. + $css_class = + $element['id']['#id'] . ' ' . $element['type']['#id'] . ' ' . $element['#id']; + $element['browser']['#prefix'] = + '
'; + $element['browser']['#suffix'] = '
'; + + // Target is the textfield that will be populated with the flickr asset id when an image is clicked. + $element['browser']['photos']['target']['#value'] = + $element['browser']['photosets']['target']['#value'] = + $element['id']['#id']; + return drupal_render($element); +} + +/** + * Flickr panda is a compilation of interesting photos, updated daily and + * maintained by Flickr. This function returns a random subset of panda photos + * based on the global per_page limit. + * + * @return a flickr photo array of panda photos + * @see http://flickr.com/explore/panda + */ +function flickrfield_get_random_panda_photos() { + $per_page = variable_get('flickr_photos_per_page', FLICKRFIELD_DEFAULT_PHOTOS_PER_PAGE); + $pandas = flickr_request('flickr.panda.getList', array()); + if(!empty($pandas)) { + $panda = $pandas['pandas']['panda'][rand(0, count($pandas) - 1)]; + if(is_array($panda)) { + $panda = current($panda); + } + } + $args = array('panda_name' => $panda, 'extras' => null, 'per_page' => $per_page, 'page' => rand(1, ceil(500 / $per_page))); + $photos = flickr_request('flickr.panda.getPhotos', $args); + + // For whatever reason, panda doesn't respect per_page. + // Manually truncate the result to per_page, randomly of course. + if(count($photos['photos']['photo']) > $per_page) { + $photos['photos']['photo'] = array_slice($photos['photos']['photo'], rand(0, count($photos['photos']['photo']) - $per_page - 1), $per_page); + } + + return $photos['photos']; +} diff -urpN flickr/field/misc/flickrfield.css flickr/field/misc/flickrfield.css --- flickr/field/misc/flickrfield.css 1969-12-31 19:00:00.000000000 -0500 +++ flickr/field/misc/flickrfield.css 2009-08-20 14:39:49.000000000 -0400 @@ -0,0 +1,39 @@ +form#node-form div.flickr-item-list .item-list ul, form#node-form div.flickr-item-list .item-list ul li { + list-style-type: none !important; +} +div.flickr-item-list .item-list li { + float: left; + padding: 0 1px; margin: 0; + text-align: center; +} +div.flickr-item-list { + display: block; +} +.flickr-pickr-pagrs .progress-disabled { + float:none !important; +} +div.wrappr-wrappr input.form-submit { + font-family:'Lucida Grande', Helvetica, Arial, Sans-Serif; + padding:2px 6px; + background-color:white; + border:1px solid rgb(221, 221, 221); + color: rgb(0, 99, 220); + letter-spacing:1px; + cursor:pointer; +} +div.wrappr-wrappr input.form-submit:hover { + color:white; + background-color:rgb(2, 89, 196); + border-color:rgb(0, 51, 102); + text-decoration:none; +} +div.wrappr-wrappr span.flickr-pager-active { + background: white; + border: none; + color: rgb(255, 0, 132); + font-weight: bold; + padding: 2px 6px; +} +div.clear { + clear: both; +} diff -urpN flickr/field/misc/flickrfield.js flickr/field/misc/flickrfield.js --- flickr/field/misc/flickrfield.js 1969-12-31 19:00:00.000000000 -0500 +++ flickr/field/misc/flickrfield.js 2009-08-20 14:14:09.000000000 -0400 @@ -0,0 +1,71 @@ +$(function() { initFlickrfieldBrowser(); }); + +var initFlickrfieldBrowser = function() { + if(Drupal.settings.flickrpickr.flickrtypefield + && $('.' + Drupal.settings.flickrpickr.flickrtypefield).length) { + $('.' + Drupal.settings.flickrpickr.flickrtypefield).each(function() { + updateFlickrfieldBrowserType($(this).attr('id'), $(this).val()); + }); + } + + if(Drupal.settings.flickrpickr.flickridfield + && $('.' + Drupal.settings.flickrpickr.flickridfield).length) { + $('.' + Drupal.settings.flickrpickr.flickridfield).each(function() { + if($('.' + $(this).attr('id')).length) { + $('.' + $(this).attr('id')).hide(); + } + }); + } +} + +var updateFlickrfieldBrowserType = function(css_class, value) { + if(!Drupal.settings.flickrpickr.flickrbrowserwrapper) { + return false; + } + $('.' + css_class + ' .' + Drupal.settings.flickrpickr.flickrbrowserwrapper + ' > div').hide(); + $('.' + css_class + ' .' + Drupal.settings.flickrpickr.flickrbrowserwrapper + ' div.'+value).slideDown(); +} + +Drupal.behaviors.flickrfield = function(context) { + // Break if necessary elements are not present + if(!Drupal.settings.flickrpickr + || !Drupal.settings.flickrpickr.imglinkclass + || !Drupal.settings.flickrpickr.flickridfield + || !Drupal.settings.flickrpickr.flickrtypefield + || !Drupal.settings.flickrpickr.flickrimgprefix + || !$('.' + Drupal.settings.flickrpickr.imglinkclass).length + || !$('.' + Drupal.settings.flickrpickr.flickridfield).length + || !$('.' + Drupal.settings.flickrpickr.flickrtypefield).length) { + return false; + } + + $('.' + Drupal.settings.flickrpickr.flickrtypefield).each(function() { + $(this).bind('change', function() { + updateFlickrfieldBrowserType($(this).attr('id'), $(this).val()); + }); + }); + + $('.' + Drupal.settings.flickrpickr.flickridfield).each(function() { + if(!$('.' + $(this).attr('id')).length) { + return false; + } + $(this).bind('focus', function() { + $('.' + $(this).attr('id')).slideDown(); + }); + $(this).children('.' + $(this).attr('id')) + }); + + $('.' + Drupal.settings.flickrpickr.imglinkclass).each(function() { + $(this).bind('click', function() { + var img = $(this).children('img:first'); + var img_id = img.attr('id'); + var asset_id = img_id.match(/[\d]+$/); + var target_id = img_id.replace('-' + asset_id, ''); + if($('#' + target_id).length) { + $('#' + target_id).val(asset_id); + } + return false; + + }) + }); +}