<commit_before>'use strict';

import RenderNode from './render_node';

/**
 * @augments RenderNode
 */
export default class InlineRenderNode extends RenderNode {

  /**
   *
   * @param {TextNode} textNode
   */
  constructor(textNode) {
    super();
    this._attributes = textNode.getAttributes();
    this._children = [textNode.getNodeValue()];
  }

  /**
   *
   * @returns {Text|Element}
   */
  getDomNode() {

    if (!this._attributes.length)
      return document.createTextNode(this._children[0]);

    // todo lol what am I doing. Code properly tired lukas!

    const map = {bold: 'strong', italic: 'em'};
    let attrs = this._attributes.slice(0);
    const el = document.createElement(map[attrs.pop()[0]]);
    let innerElement = el;

    while (attrs.length) {
      innerElement = document.createElement(map[attrs.pop()[0]]);
      el.appendChild(innerElement);
    }

    innerElement.textContent = this._children[0];

    return el;
  }

  /**
   *
   * @param that
   * @returns {InlineRenderNode}
   */
  appendAsChild(that) {

    that.removeAttributes(this._attributes);
    let currentNode = this._children[this._children.length - 1];

    if (typeof currentNode === InlineRenderNode && currentNode.canContain(that)) {
      currentNode.appendChild(that);
    } else if (that.getAttributes().length) {
      this._children.push(that);
    } else {
      this._children = this._children.concat(that.getChildren());
    }

    return this;
  }

  /**
   *
   * @param {InlineRenderNode} that
   * @returns {boolean}
   */
  canContain(that) {
    return this._attributes.length && !that.missingAttributes(this._attributes);
  }

  /**
   *
   * @param attrs
   * @returns {boolean}
   */
  missingAttributes(attrs) {
    const len = attrs.length;
    for (let i = 0; i < len; i++)
      if (this._indexOfAttribute(attrs[i]) === -1) return true;
    return false;
  }

  /**
   *
   * @param attrs
   * @returns {InlineRenderNode}
   */
  removeAttributes(attrs) {
    const len = attrs.length;
    let index = -1;
    for (let i = 0; i < len; i++)
      if ((index = this._indexOfAttribute(attrs[i])) !== -1) this._attributes.splice(index, 1);
  }

  /**
   *
   * @returns {Array}
   */
  getAttributes() {
    return this._attributes.slice(0);
  }

  /**
   *
   * @returns {Array}
   */
  getChildren() {
    return this._children.slice(0);
  }

  /**
   *
   * @param attr
   * @returns {number}
   * @private
   */
  _indexOfAttribute(attr) {
    const len = this._attributes.length;
    for (let i = 0; i < len; i++)
      if (InlineRenderNode._attributesAreEqual(this._attributes[i], attr)) return i;
    return -1;
  }

  /**
   *
   * @param a
   * @param b
   * @returns {boolean}
   * @private
   */
  static _attributesAreEqual(a, b) {
    return a[0] == b[0] && a[1] == b[1];
  }

}
<commit_msg>Finished crappy renderer with horrible code from hell<commit_after>'use strict';

import RenderNode from './render_node';

/**
 * @augments RenderNode
 */
export default class InlineRenderNode extends RenderNode {

  /**
   *
   * @param {TextNode} textNode
   */
  constructor(textNode) {
    super();
    this._attributes = textNode.getAttributes();
    this._children = [textNode.getNodeValue()];
  }

  /**
   *
   * @returns {Text|Element}
   */
  getDomNode() {

    if (!this._attributes.length)
      return document.createTextNode(this._children[0]);

    // todo lol what am I doing. Code properly tired lukas!

    const map = {bold: 'strong', italic: 'em'};
    let attrs = this._attributes.slice(0);
    const el = document.createElement(map[attrs.pop()[0]]);
    let innerElement = el;

    while (attrs.length) {
      innerElement = document.createElement(map[attrs.pop()[0]]);
      el.appendChild(innerElement);
    }

    for (let i = 0; i < this._children.length; i++) {
      if (typeof this._children[i] === 'string')
        innerElement.appendChild(document.createTextNode(this._children[i]));
      else
        innerElement.appendChild(this._children[i].getDomNode());
    }

    return el;
  }

  /**
   *
   * @param that
   * @returns {InlineRenderNode}
   */
  appendAsChild(that) {

    that.removeAttributes(this._attributes);
    let currentNode = this._children[this._children.length - 1];

    if (typeof currentNode === InlineRenderNode && currentNode.canContain(that)) {
      currentNode.appendChild(that);
    } else if (that.getAttributes().length) {
      this._children.push(that);
    } else {
      this._children = this._children.concat(that.getChildren());
    }

    return this;
  }

  /**
   *
   * @param {InlineRenderNode} that
   * @returns {boolean}
   */
  canContain(that) {
    return this._attributes.length && !that.missingAttributes(this._attributes);
  }

  /**
   *
   * @param attrs
   * @returns {boolean}
   */
  missingAttributes(attrs) {
    const len = attrs.length;
    for (let i = 0; i < len; i++)
      if (this._indexOfAttribute(attrs[i]) === -1) return true;
    return false;
  }

  /**
   *
   * @param attrs
   * @returns {InlineRenderNode}
   */
  removeAttributes(attrs) {
    const len = attrs.length;
    let index = -1;
    for (let i = 0; i < len; i++)
      if ((index = this._indexOfAttribute(attrs[i])) !== -1) this._attributes.splice(index, 1);
  }

  /**
   *
   * @returns {Array}
   */
  getAttributes() {
    return this._attributes.slice(0);
  }

  /**
   *
   * @returns {Array}
   */
  getChildren() {
    return this._children.slice(0);
  }

  /**
   *
   * @param attr
   * @returns {number}
   * @private
   */
  _indexOfAttribute(attr) {
    const len = this._attributes.length;
    for (let i = 0; i < len; i++)
      if (InlineRenderNode._attributesAreEqual(this._attributes[i], attr)) return i;
    return -1;
  }

  /**
   *
   * @param a
   * @param b
   * @returns {boolean}
   * @private
   */
  static _attributesAreEqual(a, b) {
    return a[0] == b[0] && a[1] == b[1];
  }

}
<|endoftext|>


<commit_before>function getDefaultIconTransitionProperties() {
  return {
    transitionDuration: `0.3s`,
    transitionProperty: `fill`
  };
}

function getStylesByHover(themeData, surface, on, variant) {
  const surfaceLevel = Number(surface);
  const isDynamic = variant === `dynamic`;
  const dynamicHoverIconColor = on
    ? themeData["iconButton.hover.on.iconColor"]
    : themeData["iconButton.hover.iconColor"];
  const hoverIconColor = isDynamic
    ? dynamicHoverIconColor
    : themeData["iconButton.static.iconColor"];
  const staticSurfaceLevelBackgroundColor =
    surfaceLevel <= 250
      ? themeData["iconButton.static.hover.level100To250.backgroundColor"]
      : themeData["iconButton.static.hover.level300To350.backgroundColor"];
  const staticHoverBackgroundColor = on
    ? themeData["iconButton.static.on.hover.level100To250.backgroundColor"]
    : staticSurfaceLevelBackgroundColor;
  const backgroundColor = !isDynamic
    ? staticHoverBackgroundColor
    : `transparent`;
  const staticBorderColor = on
    ? themeData["iconButton.static.on.hover.borderColor"]
    : `transparent`;
  const borderColor = !isDynamic ? staticBorderColor : `transparent`;

  return {
    backgroundColor,
    borderColor,
    boxShadow: `none`,
    "& svg *": {
      ...getDefaultIconTransitionProperties(),
      fill: hoverIconColor
    }
  };
}

function getStylesByFocus(themeData, on, variant) {
  const isDynamic = variant === `dynamic`;
  const dynamicFocusIconColor = on
    ? themeData["iconButton.focus.on.iconColor"]
    : themeData["iconButton.focus.iconColor"];
  const focusIconColor = isDynamic
    ? dynamicFocusIconColor
    : themeData["iconButton.static.iconColor"];
  const staticBorderColor = on
    ? themeData["iconButton.static.on.focus.borderColor"]
    : `transparent`;
  const borderColor = !isDynamic ? staticBorderColor : `transparent`;

  return {
    borderColor,
    boxShadow: `0 0 0 ${themeData["iconButton.focus.halo.width"]} ${
      themeData["iconButton.focus.halo.color"]
    }`,
    transitionDuration: `0.3s, 0.3s`,
    "& svg *": {
      ...getDefaultIconTransitionProperties(),
      fill: focusIconColor
    }
  };
}

function getStylesByPressed(themeData, surface, on, variant) {
  const surfaceLevel = Number(surface);
  const dynamicPressedIconColor = on
    ? themeData["iconButton.pressed.on.iconColor"]
    : themeData["iconButton.pressed.iconColor"];
  const pressedIconColor =
    variant === "dynamic"
      ? dynamicPressedIconColor
      : themeData["iconButton.static.iconColor"];
  return {
    backgroundColor:
      surfaceLevel <= 250
        ? themeData["iconButton.pressed.level100To250.backgroundColor"]
        : themeData["iconButton.pressed.level300To350.backgroundColor"],
    borderColor: `transparent`,
    transitionDuration: `0.3s, 0.3s`,
    "& svg *": {
      ...getDefaultIconTransitionProperties(),
      fill: pressedIconColor
    }
  };
}

function getStylesByDisabled(themeData) {
  return {
    opacity: themeData["component.disabled.opacity"],
    pointerEvents: `none`
  };
}

export default function stylesheet(props, themeData, density) {
  const {
    disabled,
    hasFocus,
    hasHover,
    isPressed,
    on,
    surface,
    variant
  } = props;
  const contentHeight = density === `medium-density` ? `20px` : `16px`;
  const isDynamic = variant === `dynamic`;
  const dynamicIconColor = on
    ? themeData["iconButton.on.iconColor"]
    : themeData["iconButton.iconColor"];
  const iconColor = isDynamic ? dynamicIconColor : `initial`;

  return {
    iconButton: {
      backgroundColor:
        !isDynamic && on
          ? themeData["iconButton.static.on.backgroundColor"]
          : `transparent`,
      borderColor:
        !isDynamic && on
          ? themeData["iconButton.static.on.borderColor"]
          : `transparent`,
      borderStyle: `solid`,
      borderWidth: `1px`,
      display: `inline-block`,
      position: `relative`,
      cursor: `pointer`,
      boxSizing: `border-box`,
      borderRadius: themeData["iconButton.borderRadius"],
      padding: `0`,
      height: `calc(${contentHeight} + (${
        themeData["density.spacings.extraSmall"]
      } * 2))`,
      lineHeight: `calc(${contentHeight} + (${
        themeData["density.spacings.extraSmall"]
      } * 2))`,
      width: `calc(${contentHeight} + (${
        themeData["density.spacings.extraSmall"]
      } * 2))`,
      outline: 0,
      transitionProperty: `box-shadow, background-color`,
      transitionDuration: `0.3s, 0.3s`,
      transitionTimingFunction: `cubic-bezier(0.4, 0, 0.2, 1), cubic-bezier(0.4, 0, 0.2, 1)`,
      "& svg *": {
        fill: iconColor,
        transitionDuration: `0.3s`,
        transitionProperty: `fill`
      },
      ...(hasFocus ? getStylesByFocus(themeData, on, variant) : {}),
      ...(hasHover ? getStylesByHover(themeData, surface, on, variant) : {}),
      ...(isPressed ? getStylesByPressed(themeData, surface, on, variant) : {}),
      ...(disabled ? getStylesByDisabled(themeData) : {})
    },
    iconSpacer: {
      width: `24px`
    },
    iconButtonIcon: {
      position: `absolute`,
      left: 0,
      right: 0,
      margin: `0 auto`,
      top: `50%`,
      transform: `translateY(-50%)`,
      pointerEvents: `none`
    }
  };
}
<commit_msg>fix: remove static variant's fill color<commit_after>function getDefaultIconTransitionProperties() {
  return {
    transitionDuration: `0.3s`,
    transitionProperty: `fill`
  };
}

function getStylesByHover(themeData, surface, on, variant) {
  const surfaceLevel = Number(surface);
  const isDynamic = variant === `dynamic`;
  const dynamicHoverIconColor = on
    ? themeData["iconButton.hover.on.iconColor"]
    : themeData["iconButton.hover.iconColor"];
  const hoverIconColor = isDynamic
    ? dynamicHoverIconColor
    : themeData["iconButton.static.iconColor"];
  const staticSurfaceLevelBackgroundColor =
    surfaceLevel <= 250
      ? themeData["iconButton.static.hover.level100To250.backgroundColor"]
      : themeData["iconButton.static.hover.level300To350.backgroundColor"];
  const staticHoverBackgroundColor = on
    ? themeData["iconButton.static.on.hover.level100To250.backgroundColor"]
    : staticSurfaceLevelBackgroundColor;
  const backgroundColor = !isDynamic
    ? staticHoverBackgroundColor
    : `transparent`;
  const staticBorderColor = on
    ? themeData["iconButton.static.on.hover.borderColor"]
    : `transparent`;
  const borderColor = !isDynamic ? staticBorderColor : `transparent`;

  return {
    backgroundColor,
    borderColor,
    boxShadow: `none`,
    "& svg *": {
      ...getDefaultIconTransitionProperties(),
      fill: hoverIconColor
    }
  };
}

function getStylesByFocus(themeData, on, variant) {
  const isDynamic = variant === `dynamic`;
  const dynamicFocusIconColor = on
    ? themeData["iconButton.focus.on.iconColor"]
    : themeData["iconButton.focus.iconColor"];
  const focusIconColor = isDynamic
    ? dynamicFocusIconColor
    : themeData["iconButton.static.iconColor"];
  const staticBorderColor = on
    ? themeData["iconButton.static.on.focus.borderColor"]
    : `transparent`;
  const borderColor = !isDynamic ? staticBorderColor : `transparent`;

  return {
    borderColor,
    boxShadow: `0 0 0 ${themeData["iconButton.focus.halo.width"]} ${
      themeData["iconButton.focus.halo.color"]
    }`,
    transitionDuration: `0.3s, 0.3s`,
    "& svg *": {
      ...getDefaultIconTransitionProperties(),
      fill: focusIconColor
    }
  };
}

function getStylesByPressed(themeData, surface, on, variant) {
  const surfaceLevel = Number(surface);
  const dynamicPressedIconColor = on
    ? themeData["iconButton.pressed.on.iconColor"]
    : themeData["iconButton.pressed.iconColor"];
  const pressedIconColor =
    variant === "dynamic"
      ? dynamicPressedIconColor
      : themeData["iconButton.static.iconColor"];
  return {
    backgroundColor:
      surfaceLevel <= 250
        ? themeData["iconButton.pressed.level100To250.backgroundColor"]
        : themeData["iconButton.pressed.level300To350.backgroundColor"],
    borderColor: `transparent`,
    transitionDuration: `0.3s, 0.3s`,
    "& svg *": {
      ...getDefaultIconTransitionProperties(),
      fill: pressedIconColor
    }
  };
}

function getStylesByDisabled(themeData) {
  return {
    opacity: themeData["component.disabled.opacity"],
    pointerEvents: `none`
  };
}

export default function stylesheet(props, themeData, density) {
  const {
    disabled,
    hasFocus,
    hasHover,
    isPressed,
    on,
    surface,
    variant
  } = props;
  const contentHeight = density === `medium-density` ? `20px` : `16px`;
  const isDynamic = variant === `dynamic`;
  const dynamicIconColor = on
    ? themeData["iconButton.on.iconColor"]
    : themeData["iconButton.iconColor"];
  const iconColor = isDynamic ? dynamicIconColor : ``;

  return {
    iconButton: {
      backgroundColor:
        !isDynamic && on
          ? themeData["iconButton.static.on.backgroundColor"]
          : `transparent`,
      borderColor:
        !isDynamic && on
          ? themeData["iconButton.static.on.borderColor"]
          : `transparent`,
      borderStyle: `solid`,
      borderWidth: `1px`,
      display: `inline-block`,
      position: `relative`,
      cursor: `pointer`,
      boxSizing: `border-box`,
      borderRadius: themeData["iconButton.borderRadius"],
      padding: `0`,
      height: `calc(${contentHeight} + (${
        themeData["density.spacings.extraSmall"]
      } * 2))`,
      lineHeight: `calc(${contentHeight} + (${
        themeData["density.spacings.extraSmall"]
      } * 2))`,
      width: `calc(${contentHeight} + (${
        themeData["density.spacings.extraSmall"]
      } * 2))`,
      outline: 0,
      transitionProperty: `box-shadow, background-color`,
      transitionDuration: `0.3s, 0.3s`,
      transitionTimingFunction: `cubic-bezier(0.4, 0, 0.2, 1), cubic-bezier(0.4, 0, 0.2, 1)`,
      "& svg *": {
        fill: iconColor,
        transitionDuration: `0.3s`,
        transitionProperty: `fill`
      },
      ...(hasFocus ? getStylesByFocus(themeData, on, variant) : {}),
      ...(hasHover ? getStylesByHover(themeData, surface, on, variant) : {}),
      ...(isPressed ? getStylesByPressed(themeData, surface, on, variant) : {}),
      ...(disabled ? getStylesByDisabled(themeData) : {})
    },
    iconSpacer: {
      width: `24px`
    },
    iconButtonIcon: {
      position: `absolute`,
      left: 0,
      right: 0,
      margin: `0 auto`,
      top: `50%`,
      transform: `translateY(-50%)`,
      pointerEvents: `none`
    }
  };
}
<|endoftext|>


<commit_before>'use strict';
var load_freshly_pressed = function() {
    Hm_Ajax.request([{'name': 'hm_ajax_hook', 'value': 'ajax_wordpess_freshly_pressed'}], display_wordpress_freshly_pressed);
};

var display_wordpress_freshly_pressed = function(res) {
    Hm_Message_List.update([0], res.formatted_message_list, 'wp_freshly_pressed');
    Hm_Message_List.set_message_list_state('formatted_wp_freshly_pressed')
};

var load_wp_notices_for_combined_list = function() {
    Hm_Ajax.request([{'name': 'hm_ajax_hook', 'value': 'ajax_wordpess_notifications'}], display_combined_wp_notices);
};

var load_wp_notices = function() {
    Hm_Ajax.request( [{'name': 'hm_ajax_hook', 'value': 'ajax_wordpess_notifications'}], display_wordpress_notices);
};

var display_combined_wp_notices = function(res) {
    Hm_Message_List.update([0], res.formatted_message_list, 'wp_notices');
};

var display_wordpress_notices = function(res) {
    Hm_Message_List.update([0], res.formatted_message_list, 'wp_notices');
    Hm_Message_List.set_message_list_state('formatted_wp_notice_data')
};

var wp_notice_view = function(uid, callback) {
    if (!uid) {
        uid = hm_msg_uid();
    }
    $('.msg_text_inner').html('');
    Hm_Ajax.request(
        [{'name': 'hm_ajax_hook', 'value': 'ajax_wp_notice_display'},
        {'name': 'wp_uid', 'value': uid}],
        display_wp_notice,
        [],
        false,
        callback
    );
    return false;
};

var display_wp_notice = function(res) {
    $('.msg_text').html('');
    $('.msg_text').append(res.wp_notice_headers);
    $('.msg_text').append(res.wp_notice_text);
    var path = hm_list_path();
    var uid = hm_msg_uid();
    if (hm_list_parent() == 'unread') {
        Hm_Message_List.prev_next_links('formatted_unread_data', uid);
    }
    Hm_Message_List.track_read_messages(path+'_'+uid);

};

if (hm_page_name() == 'message_list') {
    if (hm_list_path() == 'wp_notifications') {
        Hm_Message_List.page_caches.wp_notifications = 'formatted_wp_notice_data';
    }
    if (hm_list_path() == 'wp_freshly_pressed') {
        Hm_Message_List.page_caches.wp_freshly_pressed = 'formatted_wp_freshly_pressed';
    }
}
else if (hm_page_name() == 'message' && hm_list_path() == 'wp_notifications') {
    wp_notice_view();
}
<commit_msg>add prev/next links to the notification view<commit_after>'use strict';
var load_freshly_pressed = function() {
    Hm_Ajax.request([{'name': 'hm_ajax_hook', 'value': 'ajax_wordpess_freshly_pressed'}], display_wordpress_freshly_pressed);
};

var display_wordpress_freshly_pressed = function(res) {
    Hm_Message_List.update([0], res.formatted_message_list, 'wp_freshly_pressed');
    Hm_Message_List.set_message_list_state('formatted_wp_freshly_pressed')
};

var load_wp_notices_for_combined_list = function() {
    Hm_Ajax.request([{'name': 'hm_ajax_hook', 'value': 'ajax_wordpess_notifications'}], display_combined_wp_notices);
};

var load_wp_notices = function() {
    Hm_Ajax.request( [{'name': 'hm_ajax_hook', 'value': 'ajax_wordpess_notifications'}], display_wordpress_notices);
};

var display_combined_wp_notices = function(res) {
    Hm_Message_List.update([0], res.formatted_message_list, 'wp_notices');
};

var display_wordpress_notices = function(res) {
    Hm_Message_List.update([0], res.formatted_message_list, 'wp_notices');
    Hm_Message_List.set_message_list_state('formatted_wp_notice_data')
};

var wp_notice_view = function(uid, callback) {
    if (!uid) {
        uid = hm_msg_uid();
    }
    $('.msg_text_inner').html('');
    Hm_Ajax.request(
        [{'name': 'hm_ajax_hook', 'value': 'ajax_wp_notice_display'},
        {'name': 'wp_uid', 'value': uid}],
        display_wp_notice,
        [],
        false,
        callback
    );
    return false;
};

var display_wp_notice = function(res) {
    $('.msg_text').html('');
    $('.msg_text').append(res.wp_notice_headers);
    $('.msg_text').append(res.wp_notice_text);
    var path = hm_list_path();
    var uid = hm_msg_uid();
    if (hm_list_parent() == 'unread') {
        Hm_Message_List.prev_next_links('formatted_unread_data', uid);
    }
    else if (path == 'wp_notifications') {
        Hm_Message_List.prev_next_links('formatted_wp_notice_data', uid);
    }
    Hm_Message_List.track_read_messages(path+'_'+uid);

};

if (hm_page_name() == 'message_list') {
    if (hm_list_path() == 'wp_notifications') {
        Hm_Message_List.page_caches.wp_notifications = 'formatted_wp_notice_data';
    }
    if (hm_list_path() == 'wp_freshly_pressed') {
        Hm_Message_List.page_caches.wp_freshly_pressed = 'formatted_wp_freshly_pressed';
    }
}
else if (hm_page_name() == 'message' && hm_list_path() == 'wp_notifications') {
    wp_notice_view();
}
<|endoftext|>


<commit_before>jQuery(document).ready(function() {
	$ = jQuery;
 observation = {};
 observation.message = $('#message');

	jQuery( "#date" ).datepicker({
		dateFormat: 'dd.mm.yy',
		duration: 0,
		showButtonPanel: true,
		onSelect: function (date, inst) {
			observation.last_date = date;
		}
	}).width(80);
	if(observation.last_date) jQuery( "#date" ).val(observation.last_date);
	if($( "#organismn_autocomplete" ).val() == '') $( "#organismn_autocomplete" ).focus();

	function changeArtGroup(id){
		alert('not implemented');
	}

	observation.showSaveResponse = function(responseText, statusText, xhr, $form)  {
		if(responseText != null && responseText.success == true){
			observation.setMessage(Drupal.t('Observation saved successfully'), 'status', 3000);

			// on add, clear form
			if (!responseText.update) {
				$('#observation_form').trigger('reset');
				$('#species_autocomplete').html('');
				observation.hideAttributes();
				observation.hideDetMethods();
				observationmap.newOverlay.overlay.setMap(null);
				observationmap.drawingManager.setDrawingMode(google.maps.drawing.OverlayType.MARKER);
			}

			// reload table
			$('#recent_observations').flexReload();

			// scroll to top of form
			$('body,html').animate({
				scrollTop: $('#observation_form').offset().top
			});
		} else if (responseText != null) {
			observation.setMessage('• ' + responseText.message.join("
• "),'error', 5000);
		} else {
			observation.setMessage('• ' + Drupal.t('Saving failed due to unknown error.'),'error', 5000);
		}
	};

	  /**
	   * Bind the form for observations to the ajax form
	   */
	  var ajaxurl = Drupal.settings.basePath + 'observation/save';
	  if($('#observation_id').val() != ''){
		  ajaxurl = Drupal.settings.basePath + 'observation/'+ $('#observation_id').val() +'/save';
	  }

	  	var options = {
	        success:   observation.showSaveResponse,
	        url:       ajaxurl,
	        type:      'post',
	        dataType:  'json',
	    };
	    // bind form using 'ajaxForm'
		if($('#observation_form').length > 0) $('#observation_form').ajaxForm(options);

		/**
		 * Show a top message banner
		 * @param message
		 * @param type
		 * @param time
		 */
		observation.setMessage = function (message, type, time) {
			if(observation.messageTimer) window.clearTimeout(observation.messageTimer);
			observation.message.children('.messages').html(message).attr('class', 'messages').addClass(type);
			observation.message.stop().css('height', 'auto').slideDown('fast');
			if(time) observation.messageTimer = window.setTimeout(function () {
				observation.message.slideUp('fast');
			}, time);
		};

		/**
		 * Show a loading indicator
		 */
		observation.showLoading = function () {
			if(!observation.loading) {
				observation.loading = $('

').hide();
				$('body').append(observation.loading);
			}
			observation.loading.dialog({
				modal: true,
				draggable: false,
				resizable: false,
				closeOnEscape: false,
				closeText: '',
				dialogClass: 'loading',
				width: 42,
				height: 42,
				minWidth: 42,
				minHeight: 42
			});
		};

		/**
		 * Hide the loading indicator
		 */
		observation.hideLoading = function () {
			if(!observation.loading) return;
			observation.loading.dialog('close');
		};

		/**
		 * Hide all determination methods
		 */
		observation.hideDetMethods = function(){
			$("#determination_method_id option").each(function () {
                $(this).css('display','none');
              });
			observation.showDetMethod('0');
		};

		/**
		 * Show a determination method by id
		 * @param id
		 */
		observation.showDetMethod = function(id){
			$('#artgroup_detmethod_value_'+id).css('display','block');
		};

		/**
		 * Hide all attributes
		 */
		observation.hideAttributes = function(){
			$("tr[id^='attributes_tr_']").each(function () {
                $(this).css('display','none');
              });
		};

		/**
		 * Show a attribute by id
		 * @param id
		 */
		observation.showAttribute = function(id){
			$('#attributes_tr_'+id).css('display','table-row');
		};

		/**
		 * Reset the input's specially the organism related
		 */
		observation.resetOrganism = function(){
			$( "#organismn_id" ).val('');
			$( "#species_autocomplete" ).html('');
			$( "#observation_found_as_latin" ).val('false');
			$( "#observation_found_as_lang" ).val('false');
			observation.hideAttributes();
			observation.hideDetMethods();
		};

		/**
		 * Reset the autocomplete field, and the organism related
		 */
		observation.resetOrganismAutomcomplete = function(){
			$( "#organismn_autocomplete" ).val('');
			observation.resetOrganism();
		};

		/**
		 * Add another upload slot for files
		 * @param form //unused
		 */
		addUploadSlot = function(form){
			$('#picture_upload__0').clone().appendTo('#picture').css('display','block').css('height','auto');
			elemets_ids=0;
			$("div[id^='picture_upload__']").each(function () {
				$(this).attr("id", 'picture_upload__'+(elemets_ids++));
			});
		};

		/**
		 * Check the type of the selected file
		 * @param form
		 */
		checkMimeType_metaData = function(form){
			mimeType = form.files["0"].type;
			re = new RegExp('image/', 'ig');
			re2 = new RegExp('video/mp4', 'ig');
			re3 = new RegExp('audio/mpeg', 'ig');
			if(mimeType.match(re) || mimeType.match(re2) || mimeType.match(re3)) {
				return 'media';
			}else{
				return 'file';
			}
		};

		/**
		 * Opens a dialog to add meta data to a fileupload
		 * @param div
		 */
		observation.galleryMetaDataDialog = function (div) {
			file_name = div.children('input#file_input.form-file').val();
			div_id = div.attr("id");
			observation.showLoading();
			if(file_name == ''){
				alert(Drupal.t('Please select a file'));
				return;
			}
			var data = {
				fn: file_name,
				di: div_id,
			};
			$.getJSON(Drupal.settings.basePath + 'gallery/json/meta-form/', data, function (data) {
				if(data && data.form) {
					dialog = $('
');
					dialog.append($(data.form));
					dialog.dialog({
						modal: true,
						resizable: false,
						closeOnEscape: false,
						closeText: '',
						close: function (event, ui) {
							$(this).remove();
						},
						width: 700
					});
					var parform = dialog.find('input[name="uploadform"]').val();
					dialog.find('input[name="title"]').val($('#'+parform).find('input[id="meta_title"]').val());
					dialog.find('input[name="description"]').val($('#'+parform).find('input[id="meta_description"]').val());
					dialog.find('input[name="location"]').val($('#'+parform).find('input[id="meta_location"]').val());
					dialog.find('input[name="author"]').val($('#'+parform).find('input[id="meta_author"]').val());
					dialog.find('#edit-actions a').click(function (e) {
						e.preventDefault();
						$(this).closest('.ui-dialog-content').dialog('close');
					});
					dialog.find('form').submit(function (e) {
						var parform = $(this).find('input[name="uploadform"]').val();
						$('#'+parform).find('input[id="meta_title"]').val($(this).find('input[name="title"]').val());
						$('#'+parform).find('input[id="meta_description"]').val($(this).find('input[name="description"]').val());
						$('#'+parform).find('input[id="meta_location"]').val($(this).find('input[name="location"]').val());
						$('#'+parform).find('input[id="meta_author"]').val($(this).find('input[name="author"]').val());
						$(this).closest('.ui-dialog-content').dialog('close');
						return false;
					});
				}
				observation.hideLoading();
			});
		};

		/**
		 * Select or deselect all rows
		 */
		observation.toggleSelectedRows = function(status){
			$("input.gridSelect").each( function() {
				$(this).attr("checked",status);
			});
		}

		/**
		 * Export the selected table rows.
		 * If none are selected, all rows will be exported.
		 *
		 * @param table id
		 */
		observation.exportSelectedRows = function(table) {
			url = Drupal.settings.basePath + 'observation/export?';

			// collect shown column header ids, ordered
			var $flexidiv = $(table).closest('div.flexigrid');
			$flexidiv.find('div.nDiv:first').find('input.togCol').each(function() {
				if ($(this).attr('checked'))
					url += 'columns[]=' + $(this).val() + '&';
			});

			// collect selected observations
			$flexidiv.find('input.gridSelect').each(function() {
				if ($(this).attr('checked'))
					url += 'observations[]=' + $(this).val() + '&';
			});
			url = url.substring(0, url.length-1);

			// pass search, order and limit parameters
			var gridPrefs = $(table)[0].p;
			url += '&query=' + gridPrefs.query + '&qtype=' + gridPrefs.qtype;
			url += '&sortname=' + gridPrefs.sortname + '&sortorder=' + gridPrefs.sortorder;
			url += '&rp=18446744073709551615';  // max limit for sql query, select all (2^64-1) rows

			// load export url in a hidden iframe to get a download prompt
			var $status = $flexidiv.find('.pPageStat:first');
			var oldStatus = $status.text();
			$status.text(gridPrefs.procmsg);
			$('').attr('src', url).hide().appendTo('body').load(function() {
				$status.text(oldStatus);
			});
		}

		/**
		 * Show the message returned from the deletion request
		 */
		observation.showDeleteResponse = function(responseText, statusText, xhr, $form)  {
			if(responseText != null && responseText.success == true){
				observation.setMessage(responseText.message, responseText.type, 3000);
			} else if (responseText != null) {
				observation.setMessage('• ' + responseText.message.join("
• "), 'error', 5000);
			} else {
				observation.setMessage('• ' + Drupal.t('Deletion failed due to unknown error.'), 'error', 5000);
			}
		};

		/**
		 * Delete the selected rows
		 */
		observation.deleteSelectedRows = function(){
			var transportData = "";
			$("input.gridSelect").each( function() {
				if ($(this).attr('checked') == true){
					transportData += $(this).val() + ",";
				}
			});
			transportData = "{" + transportData.substring(0,transportData.length-1) + "}";

			if (transportData.length == 2){
				alert(Drupal.t('No records selected'));
				return;
			}

			var really = confirm(Drupal.t('Do you really want to delete the selected records?'));
			if (really){

				var data = {
					observations: transportData
				};

				var ajaxurl = Drupal.settings.basePath + 'observation/delete';
				$.getJSON(ajaxurl, data, function(json){
					jQuery("#observations").flexReload();
					observation.showDeleteResponse(json);
				});
			}
		}

		/**
		 * Display the batch div, holding the select-toggle, delete and export buttons
		 */
		observation.displayBatchArea = function(){
			if ($('#batch-div').length == 0){
				$('.bDiv').after('
 ' +
					'	<input type="checkbox" onClick="javascript:observation.toggleSelectedRows(this.checked)"> ' +
					'	<input type="button" id="btnDeleteSelected" disabled="true" value="' + Drupal.t('Delete') + '"> ' +
					'   <input type="button" id="btnExportSelected" value="' + Drupal.t('Export all') + '"> ' +
					'
');
				$('#btnDeleteSelected').click(function() {
					observation.deleteSelectedRows();
				});
				$('#btnExportSelected').click(function() {
					observation.exportSelectedRows('#observations');
				});
				// hide the batch div, if we are in gallery mode
				if (window.location.hash.indexOf('gallery') != -1){
					$('#batch-div').css('display', 'none');
				}
			}

			$('.bDiv :checkbox').click(function(){
				if ($('.bDiv :checked').length == 0) {
					$('#btnDeleteSelected').attr("disabled",true);
					$('#btnExportSelected').val(Drupal.t('Export all'));
				}
				else {
					$('#btnDeleteSelected').removeAttr("disabled");
					$('#btnExportSelected').val(Drupal.t('Export selected'));
				}
			});

		};

		/**
		 * get a observation on the map and zoom.. by id
		 * @param id
		 */
		Area.prototype.selectObservation = function(id) {
			if (id in this.overlaysArray) {
				if (this.selectedId != null) {
					this.overlaysArray[this.selectedId].deselect();
					this.selectedId = null;
				}
				this.selectedId = id;
				var currentOverlays = this.overlaysArray[this.selectedId];
				currentOverlays.select();

				var bounds = currentOverlays.getBounds();
				this.googlemap.fitBounds(bounds);
				this.googlemap.setZoom(this.googlemap.getZoom() - 2);
				this.showInfoWindow(id);
			} else {
				console.error("Observation not available: " + id);
			}
		};

});

<commit_msg>fix #362 reset delete/export buttons on other datatable actions<commit_after>jQuery(document).ready(function() {
	$ = jQuery;
 observation = {};
 observation.message = $('#message');

	jQuery( "#date" ).datepicker({
		dateFormat: 'dd.mm.yy',
		duration: 0,
		showButtonPanel: true,
		onSelect: function (date, inst) {
			observation.last_date = date;
		}
	}).width(80);
	if(observation.last_date) jQuery( "#date" ).val(observation.last_date);
	if($( "#organismn_autocomplete" ).val() == '') $( "#organismn_autocomplete" ).focus();

	function changeArtGroup(id){
		alert('not implemented');
	}

	observation.showSaveResponse = function(responseText, statusText, xhr, $form)  {
		if(responseText != null && responseText.success == true){
			observation.setMessage(Drupal.t('Observation saved successfully'), 'status', 3000);

			// on add, clear form
			if (!responseText.update) {
				$('#observation_form').trigger('reset');
				$('#species_autocomplete').html('');
				observation.hideAttributes();
				observation.hideDetMethods();
				observationmap.newOverlay.overlay.setMap(null);
				observationmap.drawingManager.setDrawingMode(google.maps.drawing.OverlayType.MARKER);
			}

			// reload table
			$('#recent_observations').flexReload();

			// scroll to top of form
			$('body,html').animate({
				scrollTop: $('#observation_form').offset().top
			});
		} else if (responseText != null) {
			observation.setMessage('• ' + responseText.message.join("
• "),'error', 5000);
		} else {
			observation.setMessage('• ' + Drupal.t('Saving failed due to unknown error.'),'error', 5000);
		}
	};

	  /**
	   * Bind the form for observations to the ajax form
	   */
	  var ajaxurl = Drupal.settings.basePath + 'observation/save';
	  if($('#observation_id').val() != ''){
		  ajaxurl = Drupal.settings.basePath + 'observation/'+ $('#observation_id').val() +'/save';
	  }

	  	var options = {
	        success:   observation.showSaveResponse,
	        url:       ajaxurl,
	        type:      'post',
	        dataType:  'json',
	    };
	    // bind form using 'ajaxForm'
		if($('#observation_form').length > 0) $('#observation_form').ajaxForm(options);

		/**
		 * Show a top message banner
		 * @param message
		 * @param type
		 * @param time
		 */
		observation.setMessage = function (message, type, time) {
			if(observation.messageTimer) window.clearTimeout(observation.messageTimer);
			observation.message.children('.messages').html(message).attr('class', 'messages').addClass(type);
			observation.message.stop().css('height', 'auto').slideDown('fast');
			if(time) observation.messageTimer = window.setTimeout(function () {
				observation.message.slideUp('fast');
			}, time);
		};

		/**
		 * Show a loading indicator
		 */
		observation.showLoading = function () {
			if(!observation.loading) {
				observation.loading = $('

').hide();
				$('body').append(observation.loading);
			}
			observation.loading.dialog({
				modal: true,
				draggable: false,
				resizable: false,
				closeOnEscape: false,
				closeText: '',
				dialogClass: 'loading',
				width: 42,
				height: 42,
				minWidth: 42,
				minHeight: 42
			});
		};

		/**
		 * Hide the loading indicator
		 */
		observation.hideLoading = function () {
			if(!observation.loading) return;
			observation.loading.dialog('close');
		};

		/**
		 * Hide all determination methods
		 */
		observation.hideDetMethods = function(){
			$("#determination_method_id option").each(function () {
                $(this).css('display','none');
              });
			observation.showDetMethod('0');
		};

		/**
		 * Show a determination method by id
		 * @param id
		 */
		observation.showDetMethod = function(id){
			$('#artgroup_detmethod_value_'+id).css('display','block');
		};

		/**
		 * Hide all attributes
		 */
		observation.hideAttributes = function(){
			$("tr[id^='attributes_tr_']").each(function () {
                $(this).css('display','none');
              });
		};

		/**
		 * Show a attribute by id
		 * @param id
		 */
		observation.showAttribute = function(id){
			$('#attributes_tr_'+id).css('display','table-row');
		};

		/**
		 * Reset the input's specially the organism related
		 */
		observation.resetOrganism = function(){
			$( "#organismn_id" ).val('');
			$( "#species_autocomplete" ).html('');
			$( "#observation_found_as_latin" ).val('false');
			$( "#observation_found_as_lang" ).val('false');
			observation.hideAttributes();
			observation.hideDetMethods();
		};

		/**
		 * Reset the autocomplete field, and the organism related
		 */
		observation.resetOrganismAutomcomplete = function(){
			$( "#organismn_autocomplete" ).val('');
			observation.resetOrganism();
		};

		/**
		 * Add another upload slot for files
		 * @param form //unused
		 */
		addUploadSlot = function(form){
			$('#picture_upload__0').clone().appendTo('#picture').css('display','block').css('height','auto');
			elemets_ids=0;
			$("div[id^='picture_upload__']").each(function () {
				$(this).attr("id", 'picture_upload__'+(elemets_ids++));
			});
		};

		/**
		 * Check the type of the selected file
		 * @param form
		 */
		checkMimeType_metaData = function(form){
			mimeType = form.files["0"].type;
			re = new RegExp('image/', 'ig');
			re2 = new RegExp('video/mp4', 'ig');
			re3 = new RegExp('audio/mpeg', 'ig');
			if(mimeType.match(re) || mimeType.match(re2) || mimeType.match(re3)) {
				return 'media';
			}else{
				return 'file';
			}
		};

		/**
		 * Opens a dialog to add meta data to a fileupload
		 * @param div
		 */
		observation.galleryMetaDataDialog = function (div) {
			file_name = div.children('input#file_input.form-file').val();
			div_id = div.attr("id");
			observation.showLoading();
			if(file_name == ''){
				alert(Drupal.t('Please select a file'));
				return;
			}
			var data = {
				fn: file_name,
				di: div_id,
			};
			$.getJSON(Drupal.settings.basePath + 'gallery/json/meta-form/', data, function (data) {
				if(data && data.form) {
					dialog = $('
');
					dialog.append($(data.form));
					dialog.dialog({
						modal: true,
						resizable: false,
						closeOnEscape: false,
						closeText: '',
						close: function (event, ui) {
							$(this).remove();
						},
						width: 700
					});
					var parform = dialog.find('input[name="uploadform"]').val();
					dialog.find('input[name="title"]').val($('#'+parform).find('input[id="meta_title"]').val());
					dialog.find('input[name="description"]').val($('#'+parform).find('input[id="meta_description"]').val());
					dialog.find('input[name="location"]').val($('#'+parform).find('input[id="meta_location"]').val());
					dialog.find('input[name="author"]').val($('#'+parform).find('input[id="meta_author"]').val());
					dialog.find('#edit-actions a').click(function (e) {
						e.preventDefault();
						$(this).closest('.ui-dialog-content').dialog('close');
					});
					dialog.find('form').submit(function (e) {
						var parform = $(this).find('input[name="uploadform"]').val();
						$('#'+parform).find('input[id="meta_title"]').val($(this).find('input[name="title"]').val());
						$('#'+parform).find('input[id="meta_description"]').val($(this).find('input[name="description"]').val());
						$('#'+parform).find('input[id="meta_location"]').val($(this).find('input[name="location"]').val());
						$('#'+parform).find('input[id="meta_author"]').val($(this).find('input[name="author"]').val());
						$(this).closest('.ui-dialog-content').dialog('close');
						return false;
					});
				}
				observation.hideLoading();
			});
		};

		/**
		 * Select or deselect all rows
		 */
		observation.toggleSelectedRows = function(status){
			$("input.gridSelect").each( function() {
				$(this).attr("checked",status);
			});
		}

		/**
		 * Export the selected table rows.
		 * If none are selected, all rows will be exported.
		 *
		 * @param table id
		 */
		observation.exportSelectedRows = function(table) {
			url = Drupal.settings.basePath + 'observation/export?';

			// collect shown column header ids, ordered
			var $flexidiv = $(table).closest('div.flexigrid');
			$flexidiv.find('div.nDiv:first').find('input.togCol').each(function() {
				if ($(this).attr('checked'))
					url += 'columns[]=' + $(this).val() + '&';
			});

			// collect selected observations
			$flexidiv.find('input.gridSelect').each(function() {
				if ($(this).attr('checked'))
					url += 'observations[]=' + $(this).val() + '&';
			});
			url = url.substring(0, url.length-1);

			// pass search, order and limit parameters
			var gridPrefs = $(table)[0].p;
			url += '&query=' + gridPrefs.query + '&qtype=' + gridPrefs.qtype;
			url += '&sortname=' + gridPrefs.sortname + '&sortorder=' + gridPrefs.sortorder;
			url += '&rp=18446744073709551615';  // max limit for sql query, select all (2^64-1) rows

			// load export url in a hidden iframe to get a download prompt
			var $status = $flexidiv.find('.pPageStat:first');
			var oldStatus = $status.text();
			$status.text(gridPrefs.procmsg);
			$('').attr('src', url).hide().appendTo('body').load(function() {
				$status.text(oldStatus);
			});
		}

		/**
		 * Show the message returned from the deletion request
		 */
		observation.showDeleteResponse = function(responseText, statusText, xhr, $form)  {
			if(responseText != null && responseText.success == true){
				observation.setMessage(responseText.message, responseText.type, 3000);
			} else if (responseText != null) {
				observation.setMessage('• ' + responseText.message.join("
• "), 'error', 5000);
			} else {
				observation.setMessage('• ' + Drupal.t('Deletion failed due to unknown error.'), 'error', 5000);
			}
		};

		/**
		 * Delete the selected rows
		 */
		observation.deleteSelectedRows = function(){
			var transportData = "";
			$("input.gridSelect").each( function() {
				if ($(this).attr('checked') == true){
					transportData += $(this).val() + ",";
				}
			});
			transportData = "{" + transportData.substring(0,transportData.length-1) + "}";

			if (transportData.length == 2){
				alert(Drupal.t('No records selected'));
				return;
			}

			var really = confirm(Drupal.t('Do you really want to delete the selected records?'));
			if (really){

				var data = {
					observations: transportData
				};

				var ajaxurl = Drupal.settings.basePath + 'observation/delete';
				$.getJSON(ajaxurl, data, function(json){
					jQuery("#observations").flexReload();
					observation.showDeleteResponse(json);
				});
			}
		}

		/**
		 * Display the batch div, holding the select-toggle, delete and export buttons
		 */
		observation.displayBatchArea = function(){
			if ($('#batch-div').length == 0) {
				$('.bDiv').after('
 ' +
					'	<input type="checkbox" onClick="javascript:observation.toggleSelectedRows(this.checked)"> ' +
					'	<input type="button" id="btnDeleteSelected" disabled="true" value="' + Drupal.t('Delete') + '"> ' +
					'   <input type="button" id="btnExportSelected" value="' + Drupal.t('Export all') + '"> ' +
					'
');
				$('#btnDeleteSelected').click(function() {
					observation.deleteSelectedRows();
				});
				$('#btnExportSelected').click(function() {
					observation.exportSelectedRows('#observations');
				});
				// hide the batch div, if we are in gallery mode
				if (window.location.hash.indexOf('gallery') != -1){
					$('#batch-div').css('display', 'none');
				}
			}
			else {
				$('#btnDeleteSelected').attr('disabled', true);
				$('#btnExportSelected').val(Drupal.t('Export all'));
			}

			$('.bDiv :checkbox').click(function(){
				if ($('.bDiv :checked').length == 0) {
					$('#btnDeleteSelected').attr('disabled', true);
					$('#btnExportSelected').val(Drupal.t('Export all'));
				}
				else {
					$('#btnDeleteSelected').removeAttr('disabled');
					$('#btnExportSelected').val(Drupal.t('Export selected'));
				}
			});

		};

		/**
		 * get a observation on the map and zoom.. by id
		 * @param id
		 */
		Area.prototype.selectObservation = function(id) {
			if (id in this.overlaysArray) {
				if (this.selectedId != null) {
					this.overlaysArray[this.selectedId].deselect();
					this.selectedId = null;
				}
				this.selectedId = id;
				var currentOverlays = this.overlaysArray[this.selectedId];
				currentOverlays.select();

				var bounds = currentOverlays.getBounds();
				this.googlemap.fitBounds(bounds);
				this.googlemap.setZoom(this.googlemap.getZoom() - 2);
				this.showInfoWindow(id);
			} else {
				console.error("Observation not available: " + id);
			}
		};

});

<|endoftext|>


<commit_before>test("module without setup/teardown (default)", function() {
	expect(1);
	ok(true);
});

test("expect in test", 3, function() {
	ok(true);
	ok(true);
	ok(true);
});

test("expect in test", 1, function() {
	ok(true);
});

module("setup test", {
	setup: function() {
		ok(true);
	}
});

test("module with setup", function() {
	expect(2);
	ok(true);
});

test("module with setup, expect in test call", 2, function() {
	ok(true);
});

var state;

module("setup/teardown test", {
	setup: function() {
		state = true;
		ok(true);
	},
	teardown: function() {
		ok(true);
	}
});

test("module with setup/teardown", function() {
	expect(3);
	ok(true);
});

module("setup/teardown test 2");

test("module without setup/teardown", function() {
	expect(1);
	ok(true);
});

if (typeof setTimeout !== 'undefined') {
state = 'fail';

module("teardown and stop", {
	teardown: function() {
		equal(state, "done", "Test teardown.");
	}
});

test("teardown must be called after test ended", function() {
	expect(1);
	stop();
	setTimeout(function() {
		state = "done";
		start();
	}, 13);
});

test("parameter passed to stop increments semaphore n times", function() {
	expect(1);
	stop(3);
	setTimeout(function() {
		state = "not enough starts";
		start(), start();
	}, 13);
	setTimeout(function() {
		state = "done";
		start();
	}, 15);
});

test("parameter passed to start decrements semaphore n times", function() {
	expect(1);
	stop(), stop(), stop();
	setTimeout(function() {
		state = "done";
		start(3);
	}, 18);
});

module("async setup test", {
	setup: function() {
		stop();
		setTimeout(function(){
			ok(true);
			start();
		}, 500);
	}
});

asyncTest("module with async setup", function() {
	expect(2);
	ok(true);
	start();
});

module("async teardown test", {
	teardown: function() {
		stop();
		setTimeout(function(){
			ok(true);
			start();
		}, 500);
	}
});

asyncTest("module with async teardown", function() {
	expect(2);
	ok(true);
	start();
});

module("asyncTest");

asyncTest("asyncTest", function() {
	expect(2);
	ok(true);
	setTimeout(function() {
		state = "done";
		ok(true);
		start();
	}, 13);
});

asyncTest("asyncTest", 2, function() {
	ok(true);
	setTimeout(function() {
		state = "done";
		ok(true);
		start();
	}, 13);
});

test("sync", 2, function() {
	stop();
	setTimeout(function() {
		ok(true);
		start();
	}, 13);
	stop();
	setTimeout(function() {
		ok(true);
		start();
	}, 125);
});

test("test synchronous calls to stop", 2, function() {
    stop();
    setTimeout(function(){
        ok(true, 'first');
        start();
        stop();
        setTimeout(function(){
            ok(true, 'second');
            start();
        }, 150);
    }, 150);
});
}

module("save scope", {
	setup: function() {
		this.foo = "bar";
	},
	teardown: function() {
		deepEqual(this.foo, "bar");
	}
});
test("scope check", function() {
	expect(2);
	deepEqual(this.foo, "bar");
});

module("simple testEnvironment setup", {
	foo: "bar",
	bugid: "#5311" // example of meta-data
});
test("scope check", function() {
	deepEqual(this.foo, "bar");
});
test("modify testEnvironment",function() {
	this.foo="hamster";
});
test("testEnvironment reset for next test",function() {
	deepEqual(this.foo, "bar");
});

module("testEnvironment with object", {
	options:{
		recipe:"soup",
		ingredients:["hamster","onions"]
	}
});
test("scope check", function() {
	deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions"]}) ;
});
test("modify testEnvironment",function() {
	// since we do a shallow copy, the testEnvironment can be modified
	this.options.ingredients.push("carrots");
});
test("testEnvironment reset for next test",function() {
	deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions","carrots"]}, "Is this a bug or a feature? Could do a deep copy") ;
});

module("testEnvironment tests");

function makeurl() {
	var testEnv = QUnit.current_testEnvironment;
	var url = testEnv.url || 'http://example.com/search';
	var q   = testEnv.q   || 'a search test';
	return url + '?q='+encodeURIComponent(q);
}

test("makeurl working",function() {
	equal( QUnit.current_testEnvironment, this, 'The current testEnvironment is global');
	equal( makeurl(), 'http://example.com/search?q=a%20search%20test', 'makeurl returns a default url if nothing specified in the testEnvironment');
});

module("testEnvironment with makeurl settings", {
	url: 'http://google.com/',
	q: 'another_search_test'
});
test("makeurl working with settings from testEnvironment", function() {
	equal( makeurl(), 'http://google.com/?q=another_search_test', 'rather than passing arguments, we use test metadata to form the url');
});
test("each test can extend the module testEnvironment", {
	q:'hamstersoup'
}, function() {
	equal( makeurl(), 'http://google.com/?q=hamstersoup', 'url from module, q from test');
});

module("jsDump");
test("jsDump output", function() {
	equals( QUnit.jsDump.parse([1, 2]), "[\n  1,\n  2\n]" );
	equals( QUnit.jsDump.parse({top: 5, left: 0}), "{\n  \"top\": 5,\n  \"left\": 0\n}" );
	if (typeof document !== 'undefined' && document.getElementById("qunit-header")) {
		equals( QUnit.jsDump.parse(document.getElementById("qunit-header")), "

" );
		equals( QUnit.jsDump.parse(document.getElementsByTagName("h1")), "[\n

\n]" );
	}
});

module("assertions");
test("raises",function() {
	function CustomError( message ) {
		this.message = message;
	}

	CustomError.prototype.toString = function() {
		return this.message;
	};

	raises(
		function() {
			throw "error"
		}
	);

	raises(
		function() {
			throw "error"
		},
		'raises with just a message, no expected'
	);

	raises(
		function() {
			throw new CustomError();
		},
		CustomError,
		'raised error is an instance of CustomError'
	);

	raises(
		function() {
			throw new CustomError("some error description");
		},
		/description/,
		"raised error message contains 'description'"
	);

	raises(
		function() {
			throw new CustomError("some error description");
		},
		function( err ) {
			if ( (err instanceof CustomError) && /description/.test(err) ) {
				return true;
			}
		},
		"custom validation function"
	);

});

if (typeof document !== "undefined") {

module("fixture");
test("setup", function() {
	document.getElementById("qunit-fixture").innerHTML = "foobar";
});
test("basics", function() {
	equal( document.getElementById("qunit-fixture").innerHTML, "test markup", "automatically reset" );
});

}

module("custom assertions");
(function() {
	function mod2(value, expected, message) {
		var actual = value % 2;
		QUnit.push(actual == expected, actual, expected, message);
	}
	test("mod2", function() {
		mod2(2, 0, "2 % 2 == 0");
		mod2(3, 1, "3 % 2 == 1");
	})
})();

module("recursions");

function Wrap(x) {
    this.wrap = x;
    if (x == undefined)  this.first = true;
}

function chainwrap(depth, first, prev) {
    depth = depth || 0;
    var last = prev || new Wrap();
    first = first || last;

    if (depth == 1) {
        first.wrap = last;
    }
    if (depth > 1) {
        last = chainwrap(depth-1, first, new Wrap(last));
    }

    return last;
}

test("check jsDump recursion", function() {
    expect(4);

    var noref = chainwrap(0);
    var nodump = QUnit.jsDump.parse(noref);
    equal(nodump, '{\n  "wrap": undefined,\n  "first": true\n}');

    var selfref = chainwrap(1);
    var selfdump = QUnit.jsDump.parse(selfref);
    equal(selfdump, '{\n  "wrap": recursion(-1),\n  "first": true\n}');

    var parentref = chainwrap(2);
    var parentdump = QUnit.jsDump.parse(parentref);
    equal(parentdump, '{\n  "wrap": {\n    "wrap": recursion(-2),\n    "first": true\n  }\n}');

    var circref = chainwrap(10);
    var circdump = QUnit.jsDump.parse(circref);
    ok(new RegExp("recursion\\(-10\\)").test(circdump), "(" +circdump + ") should show -10 recursion level");
});

test("check (deep-)equal recursion", function() {
    var noRecursion = chainwrap(0);
    equal(noRecursion, noRecursion, "I should be equal to me.");
    deepEqual(noRecursion, noRecursion, "... and so in depth.");

    var selfref = chainwrap(1);
    equal(selfref, selfref, "Even so if I nest myself.");
    deepEqual(selfref, selfref, "... into the depth.");

    var circref = chainwrap(10);
    equal(circref, circref, "Or hide that through some levels of indirection.");
    deepEqual(circref, circref, "... and checked on all levels!");
});

test('Circular reference with arrays', function() {

    // pure array self-ref
    var arr = [];
    arr.push(arr);

    var arrdump = QUnit.jsDump.parse(arr);

    equal(arrdump, '[\n  recursion(-1)\n]');
    equal(arr, arr[0], 'no endless stack when trying to dump arrays with circular ref');

    // mix obj-arr circular ref
    var obj = {};
    var childarr = [obj];
    obj.childarr = childarr;

    var objdump = QUnit.jsDump.parse(obj);
    var childarrdump = QUnit.jsDump.parse(childarr);

    equal(objdump, '{\n  "childarr": [\n    recursion(-2)\n  ]\n}');
    equal(childarrdump, '[\n  {\n    "childarr": recursion(-2)\n  }\n]');

    equal(obj.childarr, childarr, 'no endless stack when trying to dump array/object mix with circular ref');
    equal(childarr[0], obj, 'no endless stack when trying to dump array/object mix with circular ref');

});

test('Circular reference - test reported by soniciq in #105', function() {
    var MyObject = function() {};
    MyObject.prototype.parent = function(obj) {
        if (obj === undefined) { return this._parent; }
        this._parent = obj;
    };
    MyObject.prototype.children = function(obj) {
        if (obj === undefined) { return this._children; }
        this._children = obj;
    };

    var a = new MyObject(),
        b = new MyObject();

    var barr = [b];
    a.children(barr);
    b.parent(a);

    equal(a.children(), barr);
    deepEqual(a.children(), [b]);
});

(function() {
	var reset = QUnit.reset;
	function afterTest() {
		ok( false, "reset should not modify test status" );
	}
	module("reset");
	test("reset runs assertions", function() {
		QUnit.reset = function() {
			afterTest();
			reset.apply( this, arguments );
		};
	});
	test("reset runs assertions2", function() {
		QUnit.reset = reset;
	});
})();

module("noglobals", {
	teardown: function() {
		delete window.badGlobalVariableIntroducedInTest;
	}
});
test("let teardown clean up globals", function() {
	// this test will always pass if run without ?noglobals=true
	window.badGlobalVariableIntroducedInTest = true;
});

if (typeof setTimeout !== 'undefined') {
function testAfterDone(){
	var testName = "ensure has correct number of assertions";

	function secondAfterDoneTest(){
		QUnit.config.done = [];
		//QUnit.done = function(){};
		//because when this does happen, the assertion count parameter doesn't actually
		//work we use this test to check the assertion count.
		module("check previous test's assertion counts");
		test('count previous two test\'s assertions', function(){
			var spans = document.getElementsByTagName('span'),
			tests = [],
			countNodes;

			//find these two tests
			for (var i = 0; i < spans.length; i++) {
				if (spans[i].innerHTML.indexOf(testName) !== -1) {
					tests.push(spans[i]);
				}
			}

			//walk dom to counts
			countNodes = tests[0].nextSibling.nextSibling.getElementsByTagName('b');
			equal(countNodes[1].innerHTML, "99");
			countNodes = tests[1].nextSibling.nextSibling.getElementsByTagName('b');
			equal(countNodes[1].innerHTML, "99");
		});
	}
	QUnit.config.done = [];
	QUnit.done(secondAfterDoneTest);

	module("Synchronous test after load of page");

	asyncTest('Async test', function(){
		start();
		for (i=1;i<100;i++) {
			ok(i);
		}
	});

	test(testName, 99, function(){
		for (i=1;i<100;i++) {
			ok(i);
		}
	});

	//we need two of these types of tests in order to ensure that assertions
	//don't move between tests.
	test(testName + ' 2', 99, function(){
		for (i=1;i<100;i++) {
			ok(i);
		}
	});

}

QUnit.done(testAfterDone);

}
<commit_msg>Fix globals in test.js. ?tell wwalser to use ?noglobals everyonce in a while<commit_after>test("module without setup/teardown (default)", function() {
	expect(1);
	ok(true);
});

test("expect in test", 3, function() {
	ok(true);
	ok(true);
	ok(true);
});

test("expect in test", 1, function() {
	ok(true);
});

module("setup test", {
	setup: function() {
		ok(true);
	}
});

test("module with setup", function() {
	expect(2);
	ok(true);
});

test("module with setup, expect in test call", 2, function() {
	ok(true);
});

var state;

module("setup/teardown test", {
	setup: function() {
		state = true;
		ok(true);
	},
	teardown: function() {
		ok(true);
	}
});

test("module with setup/teardown", function() {
	expect(3);
	ok(true);
});

module("setup/teardown test 2");

test("module without setup/teardown", function() {
	expect(1);
	ok(true);
});

if (typeof setTimeout !== 'undefined') {
state = 'fail';

module("teardown and stop", {
	teardown: function() {
		equal(state, "done", "Test teardown.");
	}
});

test("teardown must be called after test ended", function() {
	expect(1);
	stop();
	setTimeout(function() {
		state = "done";
		start();
	}, 13);
});

test("parameter passed to stop increments semaphore n times", function() {
	expect(1);
	stop(3);
	setTimeout(function() {
		state = "not enough starts";
		start(), start();
	}, 13);
	setTimeout(function() {
		state = "done";
		start();
	}, 15);
});

test("parameter passed to start decrements semaphore n times", function() {
	expect(1);
	stop(), stop(), stop();
	setTimeout(function() {
		state = "done";
		start(3);
	}, 18);
});

module("async setup test", {
	setup: function() {
		stop();
		setTimeout(function(){
			ok(true);
			start();
		}, 500);
	}
});

asyncTest("module with async setup", function() {
	expect(2);
	ok(true);
	start();
});

module("async teardown test", {
	teardown: function() {
		stop();
		setTimeout(function(){
			ok(true);
			start();
		}, 500);
	}
});

asyncTest("module with async teardown", function() {
	expect(2);
	ok(true);
	start();
});

module("asyncTest");

asyncTest("asyncTest", function() {
	expect(2);
	ok(true);
	setTimeout(function() {
		state = "done";
		ok(true);
		start();
	}, 13);
});

asyncTest("asyncTest", 2, function() {
	ok(true);
	setTimeout(function() {
		state = "done";
		ok(true);
		start();
	}, 13);
});

test("sync", 2, function() {
	stop();
	setTimeout(function() {
		ok(true);
		start();
	}, 13);
	stop();
	setTimeout(function() {
		ok(true);
		start();
	}, 125);
});

test("test synchronous calls to stop", 2, function() {
    stop();
    setTimeout(function(){
        ok(true, 'first');
        start();
        stop();
        setTimeout(function(){
            ok(true, 'second');
            start();
        }, 150);
    }, 150);
});
}

module("save scope", {
	setup: function() {
		this.foo = "bar";
	},
	teardown: function() {
		deepEqual(this.foo, "bar");
	}
});
test("scope check", function() {
	expect(2);
	deepEqual(this.foo, "bar");
});

module("simple testEnvironment setup", {
	foo: "bar",
	bugid: "#5311" // example of meta-data
});
test("scope check", function() {
	deepEqual(this.foo, "bar");
});
test("modify testEnvironment",function() {
	this.foo="hamster";
});
test("testEnvironment reset for next test",function() {
	deepEqual(this.foo, "bar");
});

module("testEnvironment with object", {
	options:{
		recipe:"soup",
		ingredients:["hamster","onions"]
	}
});
test("scope check", function() {
	deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions"]}) ;
});
test("modify testEnvironment",function() {
	// since we do a shallow copy, the testEnvironment can be modified
	this.options.ingredients.push("carrots");
});
test("testEnvironment reset for next test",function() {
	deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions","carrots"]}, "Is this a bug or a feature? Could do a deep copy") ;
});

module("testEnvironment tests");

function makeurl() {
	var testEnv = QUnit.current_testEnvironment;
	var url = testEnv.url || 'http://example.com/search';
	var q   = testEnv.q   || 'a search test';
	return url + '?q='+encodeURIComponent(q);
}

test("makeurl working",function() {
	equal( QUnit.current_testEnvironment, this, 'The current testEnvironment is global');
	equal( makeurl(), 'http://example.com/search?q=a%20search%20test', 'makeurl returns a default url if nothing specified in the testEnvironment');
});

module("testEnvironment with makeurl settings", {
	url: 'http://google.com/',
	q: 'another_search_test'
});
test("makeurl working with settings from testEnvironment", function() {
	equal( makeurl(), 'http://google.com/?q=another_search_test', 'rather than passing arguments, we use test metadata to form the url');
});
test("each test can extend the module testEnvironment", {
	q:'hamstersoup'
}, function() {
	equal( makeurl(), 'http://google.com/?q=hamstersoup', 'url from module, q from test');
});

module("jsDump");
test("jsDump output", function() {
	equals( QUnit.jsDump.parse([1, 2]), "[\n  1,\n  2\n]" );
	equals( QUnit.jsDump.parse({top: 5, left: 0}), "{\n  \"top\": 5,\n  \"left\": 0\n}" );
	if (typeof document !== 'undefined' && document.getElementById("qunit-header")) {
		equals( QUnit.jsDump.parse(document.getElementById("qunit-header")), "

" );
		equals( QUnit.jsDump.parse(document.getElementsByTagName("h1")), "[\n

\n]" );
	}
});

module("assertions");
test("raises",function() {
	function CustomError( message ) {
		this.message = message;
	}

	CustomError.prototype.toString = function() {
		return this.message;
	};

	raises(
		function() {
			throw "error"
		}
	);

	raises(
		function() {
			throw "error"
		},
		'raises with just a message, no expected'
	);

	raises(
		function() {
			throw new CustomError();
		},
		CustomError,
		'raised error is an instance of CustomError'
	);

	raises(
		function() {
			throw new CustomError("some error description");
		},
		/description/,
		"raised error message contains 'description'"
	);

	raises(
		function() {
			throw new CustomError("some error description");
		},
		function( err ) {
			if ( (err instanceof CustomError) && /description/.test(err) ) {
				return true;
			}
		},
		"custom validation function"
	);

});

if (typeof document !== "undefined") {

module("fixture");
test("setup", function() {
	document.getElementById("qunit-fixture").innerHTML = "foobar";
});
test("basics", function() {
	equal( document.getElementById("qunit-fixture").innerHTML, "test markup", "automatically reset" );
});

}

module("custom assertions");
(function() {
	function mod2(value, expected, message) {
		var actual = value % 2;
		QUnit.push(actual == expected, actual, expected, message);
	}
	test("mod2", function() {
		mod2(2, 0, "2 % 2 == 0");
		mod2(3, 1, "3 % 2 == 1");
	})
})();

module("recursions");

function Wrap(x) {
    this.wrap = x;
    if (x == undefined)  this.first = true;
}

function chainwrap(depth, first, prev) {
    depth = depth || 0;
    var last = prev || new Wrap();
    first = first || last;

    if (depth == 1) {
        first.wrap = last;
    }
    if (depth > 1) {
        last = chainwrap(depth-1, first, new Wrap(last));
    }

    return last;
}

test("check jsDump recursion", function() {
    expect(4);

    var noref = chainwrap(0);
    var nodump = QUnit.jsDump.parse(noref);
    equal(nodump, '{\n  "wrap": undefined,\n  "first": true\n}');

    var selfref = chainwrap(1);
    var selfdump = QUnit.jsDump.parse(selfref);
    equal(selfdump, '{\n  "wrap": recursion(-1),\n  "first": true\n}');

    var parentref = chainwrap(2);
    var parentdump = QUnit.jsDump.parse(parentref);
    equal(parentdump, '{\n  "wrap": {\n    "wrap": recursion(-2),\n    "first": true\n  }\n}');

    var circref = chainwrap(10);
    var circdump = QUnit.jsDump.parse(circref);
    ok(new RegExp("recursion\\(-10\\)").test(circdump), "(" +circdump + ") should show -10 recursion level");
});

test("check (deep-)equal recursion", function() {
    var noRecursion = chainwrap(0);
    equal(noRecursion, noRecursion, "I should be equal to me.");
    deepEqual(noRecursion, noRecursion, "... and so in depth.");

    var selfref = chainwrap(1);
    equal(selfref, selfref, "Even so if I nest myself.");
    deepEqual(selfref, selfref, "... into the depth.");

    var circref = chainwrap(10);
    equal(circref, circref, "Or hide that through some levels of indirection.");
    deepEqual(circref, circref, "... and checked on all levels!");
});

test('Circular reference with arrays', function() {

    // pure array self-ref
    var arr = [];
    arr.push(arr);

    var arrdump = QUnit.jsDump.parse(arr);

    equal(arrdump, '[\n  recursion(-1)\n]');
    equal(arr, arr[0], 'no endless stack when trying to dump arrays with circular ref');

    // mix obj-arr circular ref
    var obj = {};
    var childarr = [obj];
    obj.childarr = childarr;

    var objdump = QUnit.jsDump.parse(obj);
    var childarrdump = QUnit.jsDump.parse(childarr);

    equal(objdump, '{\n  "childarr": [\n    recursion(-2)\n  ]\n}');
    equal(childarrdump, '[\n  {\n    "childarr": recursion(-2)\n  }\n]');

    equal(obj.childarr, childarr, 'no endless stack when trying to dump array/object mix with circular ref');
    equal(childarr[0], obj, 'no endless stack when trying to dump array/object mix with circular ref');

});

test('Circular reference - test reported by soniciq in #105', function() {
    var MyObject = function() {};
    MyObject.prototype.parent = function(obj) {
        if (obj === undefined) { return this._parent; }
        this._parent = obj;
    };
    MyObject.prototype.children = function(obj) {
        if (obj === undefined) { return this._children; }
        this._children = obj;
    };

    var a = new MyObject(),
        b = new MyObject();

    var barr = [b];
    a.children(barr);
    b.parent(a);

    equal(a.children(), barr);
    deepEqual(a.children(), [b]);
});

(function() {
	var reset = QUnit.reset;
	function afterTest() {
		ok( false, "reset should not modify test status" );
	}
	module("reset");
	test("reset runs assertions", function() {
		QUnit.reset = function() {
			afterTest();
			reset.apply( this, arguments );
		};
	});
	test("reset runs assertions2", function() {
		QUnit.reset = reset;
	});
})();

module("noglobals", {
	teardown: function() {
		delete window.badGlobalVariableIntroducedInTest;
	}
});
test("let teardown clean up globals", function() {
	// this test will always pass if run without ?noglobals=true
	window.badGlobalVariableIntroducedInTest = true;
});

if (typeof setTimeout !== 'undefined') {
function testAfterDone(){
	var testName = "ensure has correct number of assertions";

	function secondAfterDoneTest(){
		QUnit.config.done = [];
		//QUnit.done = function(){};
		//because when this does happen, the assertion count parameter doesn't actually
		//work we use this test to check the assertion count.
		module("check previous test's assertion counts");
		test('count previous two test\'s assertions', function(){
			var spans = document.getElementsByTagName('span'),
			tests = [],
			countNodes;

			//find these two tests
			for (var i = 0; i < spans.length; i++) {
				if (spans[i].innerHTML.indexOf(testName) !== -1) {
					tests.push(spans[i]);
				}
			}

			//walk dom to counts
			countNodes = tests[0].nextSibling.nextSibling.getElementsByTagName('b');
			equal(countNodes[1].innerHTML, "99");
			countNodes = tests[1].nextSibling.nextSibling.getElementsByTagName('b');
			equal(countNodes[1].innerHTML, "99");
		});
	}
	QUnit.config.done = [];
	QUnit.done(secondAfterDoneTest);

	module("Synchronous test after load of page");

	asyncTest('Async test', function(){
		start();
		for (var i = 1; i < 100; i++) {
			ok(i);
		}
	});

	test(testName, 99, function(){
		for (var i = 1; i < 100; i++) {
			ok(i);
		}
	});

	//we need two of these types of tests in order to ensure that assertions
	//don't move between tests.
	test(testName + ' 2', 99, function(){
		for (i=1;i<100;i++) {
			ok(i);
		}
	});

}

QUnit.done(testAfterDone);

}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { graphql, compose } from 'react-apollo';
import FontIcon from 'material-ui/FontIcon';

import ResultsCount from 'components/ResultsCount';
import Link from 'components/Link';
import SearchPresentation from 'components/SearchPresentation';

import {
  addSearchItem, sortBy,
} from 'actions/SearchActions';

import CampaignsQuery from 'schemas/queries/CampaignsQuery.graphql';

import s from 'styles/Search.scss';

import SearchCampaignResults from './components/SearchCampaignResults';
import SearchCampaignInputs from './components/SearchCampaignInputs';
import SearchCampaignSelections from './components/SearchCampaignSelections';

const graphqlOptions = collection => ({
  props: ({ data }) => ({
    [collection]: data[collection],
    items: data[collection],
    graphqlLoading: data.loading,
  }),
  options: ownProps => ({
    // Refresh every 5 min should be safe
    pollInterval: 60000 * 5,
    fetchPolicy: 'cache-and-network',
    ...ownProps,
  }),
});

const mapStateToProps = state => ({
  // TODO: something fancy to just pass along campaignsSearch?
  search: {
    keywords: state.campaignsSearch.keywords,
    tags: state.campaignsSearch.keywords,
    geographies: state.campaignsSearch.geographies,
  },
  sortBy: state.campaignsSearch.sortBy,
});

const ResultsCountWithData = compose(
  connect(mapStateToProps),
  graphql(CampaignsQuery, graphqlOptions('campaigns')),
)(ResultsCount);

const SearchCampaignResultsWithData = compose(
  connect(mapStateToProps),
  graphql(CampaignsQuery, graphqlOptions('campaigns')),
)(SearchCampaignResults);

const searchSortWrapper = connect(state => ({
  selected: state.campaignsSearch.sortBy.name,
  descending: state.campaignsSearch.sortBy.descending,
}));

const searchSortItems = [
  { label: 'Campaign Name', prop: 'title' },
];

class SearchCampaigns extends Component {
  static propTypes = {
    dispatch: PropTypes.func.isRequired,
  };

  addSelectedItem = (collectionName, value) => {
    this.props.dispatch(addSearchItem('campaign', collectionName, value));
  }

  sortSelect = (value) => {
    this.props.dispatch(sortBy('campaign', value));
  }

  render() {
    return (

        <Link to="/search">

            <FontIcon
              className={['material-icons', s.backArrow].join(' ')}
            >arrow_back</FontIcon>
            Search

        </Link>

          Search Campaigns

        <SearchPresentation
          addSelectedItem={this.addSelectedItem}
          sortSelect={this.sortSelect}
          resultsCount={<ResultsCountWithData />}
          searchSortWrapper={searchSortWrapper}
          searchSortItems={searchSortItems}
          searchSelections={<SearchCampaignSelections />}
          searchInputs={<SearchCampaignInputs />}
          searchResults={<SearchCampaignResultsWithData />}
        />

    );
  }
}

export default connect()(SearchCampaigns);
<commit_msg>Fixing dumb campaigns keywords search.<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { graphql, compose } from 'react-apollo';
import FontIcon from 'material-ui/FontIcon';

import ResultsCount from 'components/ResultsCount';
import Link from 'components/Link';
import SearchPresentation from 'components/SearchPresentation';

import {
  addSearchItem, sortBy,
} from 'actions/SearchActions';

import CampaignsQuery from 'schemas/queries/CampaignsQuery.graphql';

import s from 'styles/Search.scss';

import SearchCampaignResults from './components/SearchCampaignResults';
import SearchCampaignInputs from './components/SearchCampaignInputs';
import SearchCampaignSelections from './components/SearchCampaignSelections';

const graphqlOptions = collection => ({
  props: ({ data }) => ({
    [collection]: data[collection],
    items: data[collection],
    graphqlLoading: data.loading,
  }),
  options: ownProps => ({
    // Refresh every 5 min should be safe
    pollInterval: 60000 * 5,
    fetchPolicy: 'cache-and-network',
    ...ownProps,
  }),
});

const mapStateToProps = state => ({
  // TODO: something fancy to just pass along campaignsSearch?
  search: {
    keywords: state.campaignsSearch.keywords,
    tags: state.campaignsSearch.tags,
    geographies: state.campaignsSearch.geographies,
  },
  sortBy: state.campaignsSearch.sortBy,
});

const ResultsCountWithData = compose(
  connect(mapStateToProps),
  graphql(CampaignsQuery, graphqlOptions('campaigns')),
)(ResultsCount);

const SearchCampaignResultsWithData = compose(
  connect(mapStateToProps),
  graphql(CampaignsQuery, graphqlOptions('campaigns')),
)(SearchCampaignResults);

const searchSortWrapper = connect(state => ({
  selected: state.campaignsSearch.sortBy.name,
  descending: state.campaignsSearch.sortBy.descending,
}));

const searchSortItems = [
  { label: 'Campaign Name', prop: 'title' },
];

class SearchCampaigns extends Component {
  static propTypes = {
    dispatch: PropTypes.func.isRequired,
  };

  addSelectedItem = (collectionName, value) => {
    this.props.dispatch(addSearchItem('campaign', collectionName, value));
  }

  sortSelect = (value) => {
    this.props.dispatch(sortBy('campaign', value));
  }

  render() {
    return (

        <Link to="/search">

            <FontIcon
              className={['material-icons', s.backArrow].join(' ')}
            >arrow_back</FontIcon>
            Search

        </Link>

          Search Campaigns

        <SearchPresentation
          addSelectedItem={this.addSelectedItem}
          sortSelect={this.sortSelect}
          resultsCount={<ResultsCountWithData />}
          searchSortWrapper={searchSortWrapper}
          searchSortItems={searchSortItems}
          searchSelections={<SearchCampaignSelections />}
          searchInputs={<SearchCampaignInputs />}
          searchResults={<SearchCampaignResultsWithData />}
        />

    );
  }
}

export default connect()(SearchCampaigns);
<|endoftext|>


<commit_before>/* global require, module */

var os = require('os')
var util = require('util')
var http = require('http')
var EventEmitter = require('events').EventEmitter
var SsdpClient = require('node-ssdp').Client
var mdns = require('multicast-dns')
var Device = require('./Device').Device
var debug = require('debug')('chromecast-api')

var Browser = function () {
	debug('Initializing...')
	EventEmitter.call(this)
	this.init()
}

module.exports.Browser = Browser

util.inherits(Browser, EventEmitter)

Browser.prototype.update = function (device) {
	this.device = new Device(device)
	this.emit('deviceOn', this.device)
}

Browser.prototype.init = function () {
	var self = this

	//Internal storage
	var devices = {}
	var dns = this._dns = mdns()

	dns.on('response', function (response) {
		response.answers.forEach(function (a) {
			debug('DNS [PTR]: ', a)
			if (a.type === 'PTR' && a.name === '_googlecast._tcp.local') {
				var name = a.data.replace('._googlecast._tcp.local', '')
				if (!devices[name]) {
					devices[name] = {name: name, host: null}
				}
			}
		})

		var onanswer = function (a) {
			debug('DNS [A]: ', a)
			var name = a.name.replace('.local', '')
			if (a.type === 'A' && devices[name] && !devices[name].host) {
				devices[name].host = a.data

				//Emit
				self.update({
					name: name,
					addresses: [a.data]
				})
			}
		}

		response.additionals.forEach(onanswer)
		response.answers.forEach(onanswer)
	})

	var responseCallback = function (headers, statusCode, rinfo) {
		if (statusCode !== 200)
			return
		if (!headers.LOCATION)
			return

		http.get(headers.LOCATION, function (res) {
			var body = ''
			res.on('data', function (chunk) {
				body += chunk
			})
			res.on('end', function () {
				var match = body.match(/<friendlyName>(.+?)<\/friendlyName>/)
				if (!match || match.length !== 2)
					return

				var name = match[1]
				var host = rinfo.address

				if (!devices[name]) {
					//New device
					devices[name] = {name: name, host: host}

					return self.update({
						name: name,
						addresses: [host]
					})
				} else if(!devices[name].host) {
					//Update device
					devices[name].host = host

					self.update({
						name: name,
						addresses: [host]
					})
				}
			})
		})
	}

	var networkInterfaces = os.networkInterfaces()

	Object.keys(networkInterfaces).forEach(function (type) {
		networkInterfaces[type].forEach(function (networkInterface) {
			if (networkInterface.internal)
				return

			//SSDP
			var ssdpBrowser = new SsdpClient({
				unicastHost: networkInterface.address
			})
			ssdpBrowser.on('response', responseCallback)
			ssdpBrowser.search('urn:dial-multiscreen-org:service:dial:1')
		})
	})
	//MDNS
	dns.query('_googlecast._tcp.local', 'PTR')
}

Browser.prototype.stop = function () {
	var dns = this._dns
	if (dns) {
		dns.removeAllListeners()
		dns.destroy()
	}
}
<commit_msg>gc dns object<commit_after>/* global require, module */

var os = require('os')
var util = require('util')
var http = require('http')
var EventEmitter = require('events').EventEmitter
var SsdpClient = require('node-ssdp').Client
var mdns = require('multicast-dns')
var Device = require('./Device').Device
var debug = require('debug')('chromecast-api')

var Browser = function () {
	debug('Initializing...')
	EventEmitter.call(this)
	this.init()
}

module.exports.Browser = Browser

util.inherits(Browser, EventEmitter)

Browser.prototype.update = function (device) {
	this.device = new Device(device)
	this.emit('deviceOn', this.device)
}

Browser.prototype.init = function () {
	var self = this

	//Internal storage
	var devices = {}
	var dns = this._dns = mdns()

	dns.on('response', function (response) {
		response.answers.forEach(function (a) {
			debug('DNS [PTR]: ', a)
			if (a.type === 'PTR' && a.name === '_googlecast._tcp.local') {
				var name = a.data.replace('._googlecast._tcp.local', '')
				if (!devices[name]) {
					devices[name] = {name: name, host: null}
				}
			}
		})

		var onanswer = function (a) {
			debug('DNS [A]: ', a)
			var name = a.name.replace('.local', '')
			if (a.type === 'A' && devices[name] && !devices[name].host) {
				devices[name].host = a.data

				//Emit
				self.update({
					name: name,
					addresses: [a.data]
				})
			}
		}

		response.additionals.forEach(onanswer)
		response.answers.forEach(onanswer)
	})

	var responseCallback = function (headers, statusCode, rinfo) {
		if (statusCode !== 200)
			return
		if (!headers.LOCATION)
			return

		http.get(headers.LOCATION, function (res) {
			var body = ''
			res.on('data', function (chunk) {
				body += chunk
			})
			res.on('end', function () {
				var match = body.match(/<friendlyName>(.+?)<\/friendlyName>/)
				if (!match || match.length !== 2)
					return

				var name = match[1]
				var host = rinfo.address

				if (!devices[name]) {
					//New device
					devices[name] = {name: name, host: host}

					return self.update({
						name: name,
						addresses: [host]
					})
				} else if(!devices[name].host) {
					//Update device
					devices[name].host = host

					self.update({
						name: name,
						addresses: [host]
					})
				}
			})
		})
	}

	var networkInterfaces = os.networkInterfaces()

	Object.keys(networkInterfaces).forEach(function (type) {
		networkInterfaces[type].forEach(function (networkInterface) {
			if (networkInterface.internal)
				return

			//SSDP
			var ssdpBrowser = new SsdpClient({
				unicastHost: networkInterface.address
			})
			ssdpBrowser.on('response', responseCallback)
			ssdpBrowser.search('urn:dial-multiscreen-org:service:dial:1')
		})
	})
	//MDNS
	dns.query('_googlecast._tcp.local', 'PTR')
}

Browser.prototype.stop = function () {
	var dns = this._dns
	if (dns) {
		dns.removeAllListeners()
		dns.destroy()
		this._dns = null
	}
}
<|endoftext|>