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' => '',
+ '#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[] = '';
+ }
+
+ $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'] =
+ '';
+
+ // 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;
+
+ })
+ });
+}