function edit_form(&$form, &$form_state) { parent::edit_form($form, $form_state); $module_path = drupal_get_path('module', 'slick'); $optionset = $form_state['item']; $options = $optionset->options; $form['#attached']['css'][] = $module_path . '/css/admin/slick.admin--ui.css'; $form['#attached']['css'][] = $module_path . '/css/admin/slick.admin--vertical-tabs.css'; $form['#attached']['js'][] = $module_path . '/js/slick.admin.ui.js'; $form['#attributes']['class'][] = 'no-js'; $form['#attributes']['class'][] = 'form--slick'; $form['#attributes']['class'][] = 'form--compact'; $form['#attributes']['class'][] = 'form--optionset'; $form['#attributes']['class'][] = 'clearfix'; $form['info']['label']['#attributes']['class'][] = 'is-tooltip'; $form['info']['name']['#attributes']['class'][] = 'is-tooltip'; $form['info']['label']['#prefix'] = '<div class="form--slick__header has-tooltip clearfix">'; // Skins. $skins = slick_skins(TRUE); $form['skin'] = array('#type' => 'select', '#title' => t('Skin'), '#options' => $skins, '#default_value' => $optionset->skin, '#description' => t('Skins allow swappable layouts like next/prev links, split image and caption, etc. Make sure to provide a dedicated slide layout per field. However a combination of skins and options may lead to unpredictable layouts, get dirty yourself. See main <a href="@skin">README.txt</a> for details on Skins.', array('@skin' => url($module_path . '/README.txt'))), '#attributes' => array('class' => array('is-tooltip'))); $form['breakpoints'] = array('#title' => t('Breakpoints'), '#type' => 'textfield', '#description' => t('The number of breakpoints added to Responsive display.'), '#default_value' => isset($form_state['values']['breakpoints']) ? $form_state['values']['breakpoints'] : $optionset->breakpoints, '#suffix' => '</div>', '#ajax' => array('callback' => 'slick_add_breakpoints_ajax_callback', 'wrapper' => 'breakpoints-ajax-wrapper', 'event' => 'change'), '#attributes' => array('class' => array('is-tooltip'))); // Options. $form['options'] = array('#type' => 'vertical_tabs', '#tree' => TRUE); // Image styles. $image_styles = image_style_options(FALSE); $form['options']['general'] = array('#type' => 'fieldset', '#title' => t('General'), '#attributes' => array('class' => array('has-tooltip', 'fieldset--no-checkboxes-label'))); $form['options']['general']['normal'] = array('#type' => 'select', '#title' => t('Image style'), '#description' => t('Image style for the main/background image, overriden by field. Thumbnails are defined per field basis.'), '#empty_option' => t('None (original image)'), '#options' => $image_styles, '#default_value' => isset($options['general']['normal']) ? $options['general']['normal'] : '', '#attributes' => array('class' => array('is-tooltip'))); /* @todo drop it or test elementTransition.js $form['options']['general']['transition'] = array( '#type' => 'select', '#title' => t('Transition effect'), '#description' => t('Custom CSS3 transition effect.'), '#empty_option' => t('- None -'), '#options' => _slick_transition_options(), '#default_value' => isset($options['general']['transition']) ? $options['general']['transition'] : '', ); */ $form['options']['general']['template_class'] = array('#type' => 'textfield', '#title' => t('Wrapper class'), '#description' => t('Additional template wrapper classes separated by spaces to gain more control per optionset.'), '#default_value' => isset($options['general']['template_class']) ? $options['general']['template_class'] : '', '#attributes' => array('class' => array('is-tooltip'))); $form['options']['general']['goodies'] = array('#type' => 'checkboxes', '#title' => t('Goodies'), '#default_value' => !empty($options['general']['goodies']) ? array_values((array) $options['general']['goodies']) : array(), '#options' => array('pattern' => t('Use pattern overlay'), 'arrow-down' => t('Use arrow down')), '#description' => t('<ol><li>Pattern overlay is background image with pattern placed over the main stage.</li><li>Arrow down to scroll down into a certain page section, make sure to provide target selector.</li></ol>'), '#attributes' => array('class' => array('is-tooltip'))); $form['options']['general']['arrow_down_target'] = array('#type' => 'textfield', '#title' => t('Arrow down target'), '#description' => t('Valid CSS selector to scroll to, e.g.: #main, or #content.'), '#default_value' => isset($options['general']['arrow_down_target']) ? $options['general']['arrow_down_target'] : '', '#states' => array('visible' => array(':input[name*=arrow-down]' => array('checked' => TRUE))), '#attributes' => array('class' => array('is-tooltip'))); $form['options']['general']['arrow_down_offset'] = array('#type' => 'textfield', '#title' => t('Arrow down offset'), '#description' => t('Offset when scrolled down from the top.'), '#default_value' => isset($options['general']['arrow_down_offset']) ? $options['general']['arrow_down_offset'] : '', '#states' => array('visible' => array(':input[name*=arrow-down]' => array('checked' => TRUE))), '#attributes' => array('class' => array('is-tooltip'))); // Add empty suffix to style checkboxes like iOS. foreach ($form['options']['general']['goodies']['#options'] as $key => $value) { $form['options']['general']['goodies'][$key]['#field_suffix'] = ''; $form['options']['general']['goodies'][$key]['#title_display'] = 'before'; } // Main options. $slick_options = slick_get_options(); $form['options']['settings'] = array('#title' => t('Settings'), '#type' => 'fieldset', '#collapsible' => FALSE, '#tree' => TRUE, '#attributes' => array('class' => array('fieldset--settings', 'has-tooltip'))); foreach ($slick_options as $name => $values) { $form['options']['settings'][$name] = array('#title' => $values['title'], '#description' => $values['description'], '#type' => $values['type'], '#default_value' => isset($options['settings'][$name]) ? $options['settings'][$name] : $values['default'], '#attributes' => array('class' => array('is-tooltip'))); if (isset($values['field_suffix'])) { $form['options']['settings'][$name]['#field_suffix'] = $values['field_suffix']; } if ($values['type'] == 'textfield') { $form['options']['settings'][$name]['#size'] = 20; $form['options']['settings'][$name]['#maxlength'] = 255; } if (!isset($values['field_suffix']) && $values['cast'] == 'bool') { $form['options']['settings'][$name]['#field_suffix'] = ''; $form['options']['settings'][$name]['#title_display'] = 'before'; } if ($values['cast'] == 'int') { $form['options']['settings'][$name]['#maxlength'] = 60; $form['options']['settings'][$name]['#attributes']['class'][] = 'form-text--int'; } if (isset($values['states'])) { $form['options']['settings'][$name]['#states'] = $values['states']; } if (isset($values['options'])) { $form['options']['settings'][$name]['#options'] = $values['options']; } if (isset($values['empty_option'])) { $form['options']['settings'][$name]['#empty_option'] = $values['empty_option']; } // Expand textfield for easy edit. if (in_array($name, array('prevArrow', 'nextArrow'))) { $form['options']['settings'][$name]['#attributes']['class'][] = 'js-expandable'; } } // Responsive options. $form['options']['responsives'] = array('#title' => t('Responsive display'), '#type' => 'fieldset', '#description' => t('Containing breakpoints and settings objects. Settings set at a given breakpoint/screen width is self-contained and does not inherit the main settings, but defaults. Currently only supports Desktop first: starts breakpoint from the largest to smallest.'), '#collapsible' => FALSE, '#tree' => TRUE); $form['options']['responsives']['responsive'] = array('#title' => t('Responsive'), '#type' => 'fieldset', '#collapsible' => FALSE, '#attributes' => array('class' => array('has-tooltip', 'fieldset--responsive--ajax')), '#prefix' => '<div id="breakpoints-ajax-wrapper">', '#suffix' => '</div>'); $breakpoints_count = isset($form_state['values']['breakpoints']) ? $form_state['values']['breakpoints'] : $optionset->breakpoints; $form_state['breakpoints_count'] = $breakpoints_count; if ($form_state['breakpoints_count'] > 0) { $slick_options = slick_get_responsive_options($form_state['breakpoints_count']); foreach ($slick_options as $i => $values) { if ($values['type'] == 'fieldset') { $fieldset_class = drupal_clean_css_identifier(drupal_strtolower($values['title'])); $form['options']['responsives']['responsive'][$i] = array('#title' => $values['title'], '#type' => $values['type'], '#collapsible' => TRUE, '#collapsed' => TRUE, '#attributes' => array('class' => array('fieldset--responsive', 'fieldset--' . $fieldset_class, 'has-tooltip'))); foreach ($values as $key => $vals) { if (is_array($vals)) { if ($vals['type'] == 'fieldset') { if (!isset($vals['default']) && $vals['type'] == 'fieldset') { $form['options']['responsives']['responsive'][$i][$key] = array('#title' => $vals['title'], '#type' => $vals['type'], '#collapsible' => FALSE, '#collapsed' => FALSE, '#attributes' => array('class' => array('fieldset--settings', 'fieldset--' . $fieldset_class, 'has-tooltip'))); } foreach ($vals as $k => $value) { if ($value && is_array($value)) { $form['options']['responsives']['responsive'][$i][$key][$k] = array('#title' => $value['title'], '#description' => $value['description'], '#type' => $value['type'], '#attributes' => array('class' => array('is-tooltip'))); if ($value['type'] != 'fieldset') { $form['options']['responsives']['responsive'][$i][$key][$k]['#default_value'] = isset($options['responsives']['responsive'][$i][$key][$k]) ? $options['responsives']['responsive'][$i][$key][$k] : $value['default']; } if (isset($value['states'])) { // Specify proper states for the breakpoint form elements. $states = ''; switch ($k) { case 'pauseOnHover': case 'pauseOnDotsHover': case 'autoplaySpeed': $states = array('visible' => array(':input[name*="options[responsives][responsive][' . $i . '][settings][autoplay]"]' => array('checked' => TRUE))); break; case 'appendArrows': $states = array('visible' => array(':input[name*="options[responsives][responsive][' . $i . '][settings][arrows]"]' => array('checked' => TRUE))); break; case 'centerPadding': $states = array('visible' => array(':input[name*="options[responsives][responsive][' . $i . '][settings][centerMode]"]' => array('checked' => TRUE))); break; case 'touchThreshold': $states = array('visible' => array(':input[name*="options[responsives][responsive][' . $i . '][settings][touchMove]"]' => array('checked' => TRUE))); break; } if ($states) { $form['options']['responsives']['responsive'][$i][$key][$k]['#states'] = $states; } } if (isset($value['options'])) { $form['options']['responsives']['responsive'][$i][$key][$k]['#options'] = $value['options']; } if (isset($value['empty_option'])) { $form['options']['responsives']['responsive'][$i][$key][$k]['#empty_option'] = $value['empty_option']; } if (isset($value['field_suffix'])) { $form['options']['responsives']['responsive'][$i][$key][$k]['#field_suffix'] = $value['field_suffix']; } if (!isset($value['field_suffix']) && $value['cast'] == 'bool') { $form['options']['responsives']['responsive'][$i][$key][$k]['#field_suffix'] = ''; $form['options']['responsives']['responsive'][$i][$key][$k]['#title_display'] = 'before'; } } } } else { $form['options']['responsives']['responsive'][$i][$key] = array('#title' => $vals['title'], '#description' => $vals['description'], '#type' => $vals['type'], '#default_value' => isset($options['responsives']['responsive'][$i][$key]) ? $options['responsives']['responsive'][$i][$key] : $vals['default'], '#attributes' => array('class' => array('is-tooltip'))); if ($vals['type'] == 'textfield') { $form['options']['responsives']['responsive'][$i][$key]['#size'] = 20; $form['options']['responsives']['responsive'][$i][$key]['#maxlength'] = 255; } if ($vals['cast'] == 'int') { $form['options']['responsives']['responsive'][$i][$key]['#maxlength'] = 60; } if (isset($vals['states'])) { $form['options']['responsives']['responsive'][$i][$key]['#states'] = $vals['states']; } if (isset($vals['options'])) { $form['options']['responsives']['responsive'][$i][$key]['#options'] = $vals['options']; } if (isset($vals['field_suffix'])) { $form['options']['responsives']['responsive'][$i][$key]['#field_suffix'] = $vals['field_suffix']; } if (!isset($vals['field_suffix']) && $vals['cast'] == 'bool') { $form['options']['responsives']['responsive'][$i][$key]['#field_suffix'] = ''; $form['options']['responsives']['responsive'][$i][$key]['#title_display'] = 'before'; } } } } } } } }
/** * Defines a list of form elements available for the Slick. * * @return array * All available Slick form elements. * * @see http://kenwheeler.github.io/slick */ public function getSlickElements() { $elements =& drupal_static(__METHOD__, NULL); if (!isset($elements)) { $elements = array(); $elements['mobileFirst'] = array('title' => t('Mobile first'), 'description' => t('Responsive settings use mobile first calculation, or equivalent to min-width query.'), 'type' => 'checkbox'); $elements['asNavFor'] = array('title' => t('asNavFor target'), 'description' => t('Leave empty if using sub-modules to have it auto-matched. Set the slider to be the navigation of other slider (Class or ID Name). Use selector identifier ("." or "#") accordingly. If class, use the provided Wrapper class under General as needed, e.g.: if the main display has class "slick--for", and the thumbnail navigation "slick--nav", place the opposite here as its target. Or use existing classes based on optionsets, e.g.: .slick--optionset--main, or .slick--optionset--main-nav. Overriden per field formatter.'), 'type' => 'textfield'); $elements['accessibility'] = array('title' => t('Accessibility'), 'description' => t('Enables tabbing and arrow key navigation.'), 'type' => 'checkbox'); $elements['adaptiveHeight'] = array('title' => t('Adaptive height'), 'description' => t('Enables adaptive height for single slide horizontal carousels. This is useless with variableWidth.'), 'type' => 'checkbox'); $elements['autoplay'] = array('title' => t('Autoplay'), 'description' => t('Enables autoplay.'), 'type' => 'checkbox'); $elements['autoplaySpeed'] = array('title' => t('Autoplay speed'), 'description' => t('Autoplay speed in milliseconds.'), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][autoplay]"]' => array('checked' => TRUE)))); $elements['pauseOnHover'] = array('title' => t('Pause on hover'), 'description' => t('Pause autoplay on hover.'), 'type' => 'checkbox', 'states' => array('visible' => array(':input[name*="options[settings][autoplay]"]' => array('checked' => TRUE)))); $elements['pauseOnDotsHover'] = array('title' => t('Pause on dots hover'), 'description' => t('Pauses autoplay when a dot is hovered.'), 'type' => 'checkbox', 'states' => array('visible' => array(':input[name*="options[settings][autoplay]"]' => array('checked' => TRUE)))); $elements['arrows'] = array('title' => t('Arrows'), 'description' => t('Show prev/next arrows'), 'type' => 'checkbox'); $elements['prevArrow'] = array('title' => t('Previous arrow'), 'description' => t("Customize the previous arrow markups. Be sure to keep the expected class."), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][arrows]"]' => array('checked' => TRUE)))); $elements['nextArrow'] = array('title' => t('Next arrow'), 'description' => t("Customize the next arrow markups. Be sure to keep the expected class."), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][arrows]"]' => array('checked' => TRUE)))); $elements['centerMode'] = array('title' => t('Center mode'), 'description' => t('Enables centered view with partial prev/next slides. Use with odd numbered slidesToShow counts.'), 'type' => 'checkbox'); $elements['centerPadding'] = array('title' => t('Center padding'), 'description' => t('Side padding when in center mode (px or %). Be aware, too large padding at small breakpoint will screw the slide calculation with slidesToShow.'), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][centerMode]"]' => array('checked' => TRUE)))); $elements['dots'] = array('title' => t('Dots'), 'description' => t('Show dot indicators.'), 'type' => 'checkbox'); $elements['dotsClass'] = array('title' => t('Dot class'), 'description' => t('Class for slide indicator dots container. Do not prefix with dot. If you change this, edit its CSS accordingly.'), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][dots]"]' => array('checked' => TRUE)))); $elements['appendDots'] = array('title' => t('Append dots'), 'description' => t('Change where the navigation dots are attached (Selector, htmlString). If you change this, be sure to provide its relevant markup. E.g.: try the supported markup ".slick__arrow" without quotes to put dots within .slick__arrow. Be sure to enable arrows in such a case.'), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][dots]"]' => array('checked' => TRUE)))); $elements['draggable'] = array('title' => t('Draggable'), 'description' => t('Enable mouse dragging.'), 'type' => 'checkbox'); $elements['fade'] = array('title' => t('Fade'), 'description' => t('Enable fade. Warning! This wants slidesToShow 1. Larger than 1, and Slick may be screwed up.'), 'type' => 'checkbox'); $elements['focusOnSelect'] = array('title' => t('Focus on select'), 'description' => t('Enable focus on selected element (click).'), 'type' => 'checkbox'); $elements['infinite'] = array('title' => t('Infinite'), 'description' => t('Infinite loop sliding.'), 'type' => 'checkbox'); $elements['initialSlide'] = array('title' => t('Initial slide'), 'description' => t('Slide to start on.'), 'type' => 'textfield'); $elements['lazyLoad'] = array('title' => t('Lazy load'), 'description' => t("Set lazy loading technique. 'ondemand' will load the image as soon as you slide to it, 'progressive' loads one image after the other when the page loads. Note: dummy image is no good for ondemand. If ondemand fails to generate images, try progressive instead. Or use <a href='@url' target='_blank'>imageinfo_cache</a>. To share images for Pinterest, leave empty, otherwise no way to read actual image src.", array('@url' => '//www.drupal.org/project/imageinfo_cache')), 'type' => 'select', 'options' => drupal_map_assoc(array('ondemand', 'progressive')), 'empty_option' => t('- None -')); $elements['respondTo'] = array('title' => t('Respond to'), 'description' => t("Width that responsive object responds to. Can be 'window', 'slider' or 'min' (the smaller of the two)."), 'type' => 'select', 'options' => drupal_map_assoc(array('window', 'slider', 'min'))); $elements['rtl'] = array('title' => t('RTL'), 'description' => t("Change the slider's direction to become right-to-left."), 'type' => 'checkbox'); $elements['rows'] = array('title' => t('Rows'), 'description' => t("Setting this to more than 1 initializes grid mode. Use slidesPerRow to set how many slides should be in each row."), 'type' => 'textfield'); $elements['slidesPerRow'] = array('title' => t('Slides per row'), 'description' => t("With grid mode intialized via the rows option, this sets how many slides are in each grid row."), 'type' => 'textfield'); $elements['slide'] = array('title' => t('Slide element'), 'description' => t("Element query to use as slide. Slick will use any direct children as slides, without having to specify which tag or selector to target."), 'type' => 'textfield'); $elements['slidesToShow'] = array('title' => t('Slides to show'), 'description' => t('Number of slides to show at a time. If 1, it will behave like slideshow, more than 1 a carousel. Provide more if it is a thumbnail navigation with asNavFor. Only works with odd number slidesToShow counts when using centerMode (e.g.: 3, 5, 7, etc.). Not-compatible with variableWidth.'), 'type' => 'textfield'); $elements['slidesToScroll'] = array('title' => t('Slides to scroll'), 'description' => t('Number of slides to scroll at a time, or steps at each scroll.'), 'type' => 'textfield'); $elements['speed'] = array('title' => t('Speed'), 'description' => t('Slide/Fade animation speed in milliseconds.'), 'type' => 'textfield', 'field_suffix' => 'ms'); $elements['swipe'] = array('title' => t('Swipe'), 'description' => t('Enable swiping.'), 'type' => 'checkbox'); $elements['swipeToSlide'] = array('title' => t('Swipe to slide'), 'description' => t('Allow users to drag or swipe directly to a slide irrespective of slidesToScroll.'), 'type' => 'checkbox', 'states' => array('visible' => array(':input[name*="options[settings][swipe]"]' => array('checked' => TRUE)))); $elements['edgeFriction'] = array('title' => t('Edge friction'), 'description' => t("Resistance when swiping edges of non-infinite carousels. If you don't want resistance, set it to 1."), 'type' => 'textfield'); $elements['touchMove'] = array('title' => t('Touch move'), 'description' => t('Enable slide motion with touch.'), 'type' => 'checkbox'); $elements['touchThreshold'] = array('title' => t('Touch threshold'), 'description' => t('Swipe distance threshold.'), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][touchMove]"]' => array('checked' => TRUE)))); $elements['useCSS'] = array('title' => t('Use CSS'), 'description' => t('Enable/Disable CSS Transitions.'), 'type' => 'checkbox'); $elements['cssEase'] = array('title' => t('CSS ease'), 'description' => t('CSS3 animation easing. <a href="@ceaser">Learn</a> <a href="@bezier">more</a>. Ignored if <strong>CSS ease override</strong> is provided.', array('@ceaser' => '//matthewlein.com/ceaser/', '@bezier' => '//cubic-bezier.com')), 'type' => 'textfield', 'states' => array('visible' => array(':input[name*="options[settings][useCSS]"]' => array('checked' => TRUE)))); $elements['cssEaseBezier'] = array('type' => 'hidden'); $elements['cssEaseOverride'] = array('title' => t('CSS ease override'), 'description' => t('If provided, this will override the CSS ease with the pre-defined CSS easings based on <a href="@ceaser">CSS Easing Animation Tool</a>. Leave it empty to use your own CSS ease.', array('@ceaser' => '//matthewlein.com/ceaser/')), 'type' => 'select', 'options' => _slick_css_easing_options(), 'empty_option' => t('- None -'), 'states' => array('visible' => array(':input[name*="options[settings][useCSS]"]' => array('checked' => TRUE)))); $elements['easing'] = array('title' => t('jQuery easing'), 'description' => t('Add easing for jQuery animate as fallback. Use with <a href="@easing">easing</a> libraries or default easing methods. This will be ignored and replaced by CSS ease for supporting browsers, or effective if useCSS is disabled.', array('@easing' => '//gsgd.co.uk/sandbox/jquery/easing/')), 'type' => 'select', 'options' => _slick_easing_options(), 'empty_option' => t('- None -')); $elements['variableWidth'] = array('title' => t('variableWidth'), 'description' => t('Disables automatic slide width calculation. Best with uniform image heights, use scale height image effect. Useless with adaptiveHeight, and non-uniform image heights. Useless with slidesToShow > 1 if the container is smaller than the amount of visible slides. Troubled with lazyLoad ondemand.'), 'type' => 'checkbox'); $elements['vertical'] = array('title' => t('Vertical'), 'description' => t('Vertical slide direction. See <a href="@url" target="_blank">relevant issue</a>.', array('@url' => '//github.com/kenwheeler/slick/issues/1001')), 'type' => 'checkbox'); $elements['verticalSwiping'] = array('title' => t('Vertical swiping'), 'description' => t('Changes swipe direction to vertical.'), 'type' => 'checkbox', 'states' => array('visible' => array(':input[name*="options[settings][vertical]"]' => array('checked' => TRUE)))); $elements['waitForAnimate'] = array('title' => t('waitForAnimate'), 'description' => t('Ignores requests to advance the slide while animating.'), 'type' => 'checkbox'); // Clone the default values. $slick_options = slick_get_options(); foreach ($slick_options as $name => $value) { if (isset($elements[$name])) { $elements[$name]['default'] = $value; } } // Allows form elements information to be altered. drupal_alter('slick_ui_elements_info', $elements); } return $elements; }