<commit_before>window.APT_OPTIONS.config();

require(['jquery', 'js/quickvm_sup',
	 // jQuery modules
	 'bootstrap','filestyle'],
function ($, sup)
{
    'use strict';

    function initialize()
    {
	window.APT_OPTIONS.initialize(sup);
	try {
	    $('#rspecfile').change(function() {
		var reader = new FileReader();
		reader.onload = function(event) {
		    var content = event.target.result;

		    ShowRspecContent(content);
		};
		reader.readAsText(this.files[0]);
	    });
	}
	catch (e) {
	    alert(e);
	}

	$.fn.animateBackgroundHighlight = function(highlightColor, duration) {
	    var highlightBg = highlightColor || "#FFFF9C";
	    var animateMs = duration || 1500;
	    var originalBg = this.css("backgroundColor");
	    console.log(originalBg);
	};

	$('#showtopo_modal_button').click(function (event) {
	    event.preventDefault();
	    // The rspec is taken from the text area.
	    ShowRspecContent($('#profile_rspec').val());
	});
	$('#expand_rspec_modal_button').click(function (event) {
	    $('#modal_profile_rspec_textarea').val(
		$('#profile_rspec_textarea').val());
	    $('#rspec_modal').modal({'backdrop':'static','keyboard':false});
	    $('#rspec_modal').modal('show');
	});
	$('#collapse_rspec_modal_button').click(function (event) {
	    $('#profile_rspec_textarea').val(
		$('#modal_profile_rspec_textarea').val());
	    $('#rspec_modal').modal('hide');
	    $('#modal_profile_rspec_textarea').val("");
	    $('#profile_rspec_textarea').css({"opacity":"0.2"});
	    $('#profile_rspec_textarea').animate({"opacity":"1.0"}, 1500);
	});
	// Enable the Modify button if the form changes.
        $('#quickvm_create_profile_form :input').each(function() {
	    // Need to use keyup since an input does not "change"
	    // until focus is lost.
	    $(this).keyup(function() {
		$('#profile_submit_button').prop('disabled', false);
	    });
	});
	// This one for the checkboxes.
        $('#quickvm_create_profile_form').change(function() {
	    $('#profile_submit_button').prop('disabled', false);
	});
    }

    //
    // Show the rspec text in the modal.
    //
    function ShowRspecContent(content)
    {
	var xmlDoc = $.parseXML(content);
	var xml    = $(xmlDoc);
	var topo   = sup.ConvertManifestToJSON(null, xml);
	console.info(topo);

	sup.ShowModal("#quickvm_topomodal");

	// Subtract -2 cause of the border.
	sup.maketopmap("#showtopo_nopicker",
 		   ($("#showtopo_nopicker").outerWidth() - 2),
		   300, topo);
    }

    $(document).ready(initialize);
});
<commit_msg>Minor bug fix.<commit_after>window.APT_OPTIONS.config();

require(['jquery', 'js/quickvm_sup',
	 // jQuery modules
	 'bootstrap','filestyle'],
function ($, sup)
{
    'use strict';

    function initialize()
    {
	window.APT_OPTIONS.initialize(sup);
	try {
	    $('#rspecfile').change(function() {
		var reader = new FileReader();
		reader.onload = function(event) {
		    var content = event.target.result;

		    ShowRspecContent(content);
		};
		reader.readAsText(this.files[0]);
	    });
	}
	catch (e) {
	    alert(e);
	}

	$.fn.animateBackgroundHighlight = function(highlightColor, duration) {
	    var highlightBg = highlightColor || "#FFFF9C";
	    var animateMs = duration || 1500;
	    var originalBg = this.css("backgroundColor");
	    console.log(originalBg);
	};

	$('#showtopo_modal_button').click(function (event) {
	    event.preventDefault();
	    // The rspec is taken from the text area.
	    ShowRspecContent($('#profile_rspec_textarea').val());
	});
	$('#expand_rspec_modal_button').click(function (event) {
	    $('#modal_profile_rspec_textarea').val(
		$('#profile_rspec_textarea').val());
	    $('#rspec_modal').modal({'backdrop':'static','keyboard':false});
	    $('#rspec_modal').modal('show');
	});
	$('#collapse_rspec_modal_button').click(function (event) {
	    // Copy back to the plain textarea and kill the modal contents.
	    // The topo is drawn from the plain textarea.
	    $('#profile_rspec_textarea').val(
		$('#modal_profile_rspec_textarea').val());
	    $('#rspec_modal').modal('hide');
	    $('#modal_profile_rspec_textarea').val("");
	    $('#profile_rspec_textarea').css({"opacity":"0.2"});
	    $('#profile_rspec_textarea').animate({"opacity":"1.0"}, 1500);
	});
	// Enable the Modify button if the form changes.
        $('#quickvm_create_profile_form :input').each(function() {
	    // Need to use keyup since an input does not "change"
	    // until focus is lost.
	    $(this).keyup(function() {
		$('#profile_submit_button').prop('disabled', false);
	    });
	});
	// This one for the checkboxes.
        $('#quickvm_create_profile_form').change(function() {
	    $('#profile_submit_button').prop('disabled', false);
	});
    }

    //
    // Show the rspec text in the modal.
    //
    function ShowRspecContent(content)
    {
	var xmlDoc = $.parseXML(content);
	var xml    = $(xmlDoc);
	var topo   = sup.ConvertManifestToJSON(null, xml);
	console.info(topo);

	sup.ShowModal("#quickvm_topomodal");

	// Subtract -2 cause of the border.
	sup.maketopmap("#showtopo_nopicker",
 		   ($("#showtopo_nopicker").outerWidth() - 2),
		   300, topo);
    }

    $(document).ready(initialize);
});
<|endoftext|>


<commit_before>/**
 * Arrays of compound selectors and combinators that form a complex selector
 * when interleaved.
 *
 * @typedef {{
 *   compoundSelectors: !Array<string>,
 *   combinators: !Array<string>,
 * }}
 */
export let ComplexSelectorParts;

/**
 * @type {!Map<string, {end: string, matchNestedParens: boolean}>}
 */
const PARENS = new Map([
  ['(', {end: ')', matchNestedParens: true}],
  ['[', {end: ']', matchNestedParens: true}],
  ['"', {end: '"', matchNestedParens: false}],
  ["'", {end: "'", matchNestedParens: false}],
]);

/**
 * @param {string} str
 * @param {!Array<string>} queryChars
 * @param {boolean} matchNestedParens
 * @return {number}
 */
const findNext = (str, queryChars, matchNestedParens = true) => {
  for (let i = 0; i < str.length; i++) {
    if (str[i] === '\\' && i < str.length - 1 && str[i + 1] !== '\n') {
      // Skip escaped character.
      i++;
    } else if (queryChars.includes(str[i])) {
      return i;
    } else if (matchNestedParens && PARENS.has(str[i])) {
      const parenInfo = PARENS.get(str[i]);
      i += findNext(
        str.substring(i + 1),
        [parenInfo.end],
        parenInfo.matchNestedParens
      );
      continue;
    }

    // Do nothing, let `i++` happen.
  }

  // Reached the end of the string without finding a final char.
  return str.length;
};

/**
 * @type {!Array<string>}
 */
const COMBINATORS = [' ', '>', '~', '+'];

/**
 * @param {string} str
 * @return {!ComplexSelectorParts}
 */
const parseComplexSelector = (str) => {
  /**
   * @type {!Array<string>}
   */
  let chunks = [];

  while (str.length) {
    const index = findNext(str, COMBINATORS);
    if (index === 0) {
      chunks.push(str[0]);
      str = str.substring(1);
    } else {
      chunks.push(str.substring(0, index));
      str = str.substring(index);
    }
  }

  // Remove leading whitespace.
  while (chunks[0] === ' ') {
    chunks.shift();
  }

  // Remove trailing whitespace.
  while (chunks[chunks.length - 1] === ' ') {
    chunks.pop();
  }

  // Remove whitespace next to combinators.
  chunks = chunks.filter((x, i) => {
    return !(
      x === ' ' &&
      (COMBINATORS.includes(chunks[i - 1]) ||
        COMBINATORS.includes(chunks[i + 1]))
    );
  });

  /**
   * @type {!Array<string>}
   */
  const compoundSelectors = [];

  /**
   * @type {!Array<string>}
   */
  const combinators = [];

  for (let i = 0; i < chunks.length; i++) {
    if (i % 2 === 0) {
      compoundSelectors.push(chunks[i]);
    } else {
      combinators.push(chunks[i]);
    }
  }

  return {
    compoundSelectors,
    combinators,
  };
};

/**
 * @param {string} str
 * @return {!Array<!ComplexSelectorParts>}
 */
export const parseSelectorList = (str) => {
  const results = [];

  while (str.length) {
    const index = findNext(str, [',']);
    results.push(parseComplexSelector(str.substring(0, index)));
    str = str.substring(index + 1);
  }

  return results;
};
<commit_msg>Remove outer whitespace early with `trim` instead.<commit_after>/**
 * Arrays of compound selectors and combinators that form a complex selector
 * when interleaved.
 *
 * @typedef {{
 *   compoundSelectors: !Array<string>,
 *   combinators: !Array<string>,
 * }}
 */
export let ComplexSelectorParts;

/**
 * @type {!Map<string, {end: string, matchNestedParens: boolean}>}
 */
const PARENS = new Map([
  ['(', {end: ')', matchNestedParens: true}],
  ['[', {end: ']', matchNestedParens: true}],
  ['"', {end: '"', matchNestedParens: false}],
  ["'", {end: "'", matchNestedParens: false}],
]);

/**
 * @param {string} str
 * @param {!Array<string>} queryChars
 * @param {boolean} matchNestedParens
 * @return {number}
 */
const findNext = (str, queryChars, matchNestedParens = true) => {
  for (let i = 0; i < str.length; i++) {
    if (str[i] === '\\' && i < str.length - 1 && str[i + 1] !== '\n') {
      // Skip escaped character.
      i++;
    } else if (queryChars.includes(str[i])) {
      return i;
    } else if (matchNestedParens && PARENS.has(str[i])) {
      const parenInfo = PARENS.get(str[i]);
      i += findNext(
        str.substring(i + 1),
        [parenInfo.end],
        parenInfo.matchNestedParens
      );
      continue;
    }

    // Do nothing, let `i++` happen.
  }

  // Reached the end of the string without finding a final char.
  return str.length;
};

/**
 * @type {!Array<string>}
 */
const COMBINATORS = [' ', '>', '~', '+'];

/**
 * @param {string} str
 * @return {!ComplexSelectorParts}
 */
const parseComplexSelector = (str) => {
  str = str.trim();

  /**
   * @type {!Array<string>}
   */
  let chunks = [];

  while (str.length) {
    const index = findNext(str, COMBINATORS);
    if (index === 0) {
      chunks.push(str[0]);
      str = str.substring(1);
    } else {
      chunks.push(str.substring(0, index));
      str = str.substring(index);
    }
  }

  // Remove whitespace next to combinators.
  chunks = chunks.filter((x, i) => {
    return !(
      x === ' ' &&
      (COMBINATORS.includes(chunks[i - 1]) ||
        COMBINATORS.includes(chunks[i + 1]))
    );
  });

  /**
   * @type {!Array<string>}
   */
  const compoundSelectors = [];

  /**
   * @type {!Array<string>}
   */
  const combinators = [];

  for (let i = 0; i < chunks.length; i++) {
    if (i % 2 === 0) {
      compoundSelectors.push(chunks[i]);
    } else {
      combinators.push(chunks[i]);
    }
  }

  return {
    compoundSelectors,
    combinators,
  };
};

/**
 * @param {string} str
 * @return {!Array<!ComplexSelectorParts>}
 */
export const parseSelectorList = (str) => {
  const results = [];

  while (str.length) {
    const index = findNext(str, [',']);
    results.push(parseComplexSelector(str.substring(0, index)));
    str = str.substring(index + 1);
  }

  return results;
};
<|endoftext|>


<commit_before>define(function () {

/**
 * Licensed under the standard MIT license:
 *
 * Copyright 2011 Joseph Gentle.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * See: https://github.com/share/ShareJS/blob/master/LICENSE
 */

/* This contains the textarea binding for ShareJS. This binding is really
 * simple, and a bit slow on big documents (Its O(N). However, it requires no
 * changes to the DOM and no heavy libraries like ace. It works for any kind of
 * text input field.
 *
 * You probably want to use this binding for small fields on forms and such.
 * For code editors or rich text editors or whatever, I recommend something
 * heavier.
 */

/* applyChange creates the edits to convert oldval -> newval.
 *
 * This function should be called every time the text element is changed.
 * Because changes are always localised, the diffing is quite easy. We simply
 * scan in from the start and scan in from the end to isolate the edited range,
 * then delete everything that was removed & add everything that was added.
 * This wouldn't work for complex changes, but this function should be called
 * on keystroke - so the edits will mostly just be single character changes.
 * Sometimes they'll paste text over other text, but even then the diff
 * generated by this algorithm is correct.
 *
 * This algorithm is O(N). I suspect you could speed it up somehow using regular expressions.
 */
var applyChange = function(ctx, oldval, newval) {
    // Strings are immutable and have reference equality. I think this test is O(1), so its worth doing.
    if (oldval === newval) {
        return;
    }

    var commonStart = 0;
    while (oldval.charAt(commonStart) === newval.charAt(commonStart)) {
        commonStart++;
    }

    var commonEnd = 0;
    while (oldval.charAt(oldval.length - 1 - commonEnd) === newval.charAt(newval.length - 1 - commonEnd) &&
        commonEnd + commonStart < oldval.length && commonEnd + commonStart < newval.length) {
        commonEnd++;
    }

    var bugz = {
        commonStart:commonStart,
        commonEnd:commonEnd,
        oldvalLength: oldval.length,
        newvalLength: newval.length
    };
    if (oldval.length !== commonStart + commonEnd) {
        if (ctx.localChange) { ctx.localChange(true); }
        ctx.remove(commonStart, oldval.length - commonStart - commonEnd);
    }
    if (newval.length !== commonStart + commonEnd) {
        if (ctx.localChange) { ctx.localChange(true); }
        ctx.insert(commonStart, newval.slice(commonStart, newval.length - commonEnd));
    }
};

/**
 * Fix issues with textarea content which is different per-browser.
 */
var cannonicalize = function (content) {

    return content.replace(/\r\n/g, '\n');
};

// Attach a textarea to a document's editing context.
//
// The context is optional, and will be created from the document if its not
// specified.
var attachTextarea = function(elem, ctx) {

    // initial state will always fail the !== check in genop.
    var content = {};
    var newSelection;

    // Replace the content of the text area with newText, and transform the
    // current cursor by the specified function.
    var replaceText = function(newText, transformCursor) {
        if (transformCursor) {
            newSelection = [transformCursor(elem.selectionStart), transformCursor(elem.selectionEnd)];
        }

        // Fixate the window's scroll while we set the element's value. Otherwise
        // the browser scrolls to the element.
        var scrollTop = elem.scrollTop;
        elem.value = newText;
        content = elem.value; // Not done on one line so the browser can do newline conversion.
        if (elem.scrollTop !== scrollTop) { elem.scrollTop = scrollTop; }

        // Setting the selection moves the cursor. We'll just have to let your
        // cursor drift if the element isn't active, though usually users don't
        // care.
        if (newSelection && window.document.activeElement === elem) {
            elem.selectionStart = newSelection[0];
            elem.selectionEnd = newSelection[1];
        }
    };

  //replaceText(ctx.get());

  // *** remote -> local changes

  ctx.onRemove(function(pos, length) {
    var transformCursor = function(cursor) {
      // If the cursor is inside the deleted region, we only want to move back to the start
      // of the region. Hence the Math.min.
      return pos < cursor ? cursor - Math.min(length, cursor - pos) : cursor;
    };
    replaceText(ctx.getUserDoc(), transformCursor);
  });

  ctx.onInsert(function(pos, text) {
    var transformCursor = function(cursor) {
      return pos < cursor ? cursor + text.length : cursor;
    };
    replaceText(ctx.getUserDoc(), transformCursor);
  });

  // *** local -> remote changes

  // This function generates operations from the changed content in the textarea.
  var genOp = function() {
    // In a timeout so the browser has time to propogate the event's changes to the DOM.
    setTimeout(function() { var val = elem.value;
      if (val !== content) {
        applyChange(ctx, ctx.getUserDoc(), cannonicalize(val));
      }
    }, 0);
  };

  var eventNames = ['textInput', 'keydown', 'keyup', 'select', 'cut', 'paste'];
  for (var i = 0; i < eventNames.length; i++) {
    var e = eventNames[i];
    if (elem.addEventListener) {
      elem.addEventListener(e, genOp, false);
    } else {
      elem.attachEvent('on' + e, genOp);
    }
  }

  ctx.detach = function() {
    for (var i = 0; i < eventNames.length; i++) {
      var e = eventNames[i];
      if (elem.removeEventListener) {
        elem.removeEventListener(e, genOp, false);
      } else {
        elem.detachEvent('on' + e, genOp);
      }
    }
  };

  ctx.bumpSharejs = genOp;

  return ctx;
};

return { attach: attachTextarea };
});
<commit_msg>remove sharejs<commit_after><|endoftext|>


<commit_before>(function () {
    var tmp = UtilityBuild(['dmUtil'],function(obj){
        "use strict";
        //
        // Dependencies
        var cssSelector = obj.doc.querySelector.bind(obj.doc)
        ,aEventListener = obj.EventUtility.aboutHandler.addListener
        //
        // Boolean Variables
        ,mouse_hover = false
        ,click_on = false
        ,id = 0
        //
        // Dom Element
        ,tab1 = cssSelector("#horizontal-nav .horizontal-nav-wrapper nav #tab3")
        ,tab2 = cssSelector("#horizontal-nav .horizontal-nav-wrapper nav #tab4")
        ,pan1 = cssSelector("#pannel3")
        ,pan2 = cssSelector("#pannel4")
        ,sch = cssSelector(".header-wrapper .search")
        ,card_prev = cssSelector(".cardslide-prev")
        ,card_next = null
        ,card_frame = null
        ,presentation_width = 0
        ,card_left = 0
        //
        // Animations Core function
        ,opacPan = function opacPan(delta) { panell.style.opacity = 1 * delta + ""; }
        ,endPan = function endPan() { panell.removeAttribute("style"); }
        ,animations = obj.AnimateObject(200,300,'quadratic',opacPan,endPan)
        ,panell = null
        //
        // Event Callback function
        ,gestureEvent = function gestureEvent(evt) {
            var subject = animations
            ,aria_attr = "";

            switch (evt.type) {
            case 'mouseover':
                if (!mouse_hover) {
                mouse_hover = true;
                obj.animatedFrame.cancel(id);
                evt.currentTarget.setAttribute("aria-expanded", "true");
                aria_attr = evt.currentTarget.getAttribute("aria-controls");
                if (aria_attr === 'pannel3') {
                    panell = pan1;
                } else if (aria_attr === 'pannel4') {
                    panell = pan2;
                }
                subject.startTimeCount();
                subject.timePassed = subject.getStartTime();
                id = obj.animatedFrame.request(subject.animate.bind(subject));
                }
                break;
            case 'mouseout':
                mouse_hover = false;
                evt.currentTarget.setAttribute("aria-expanded", "false");
                break;
            case 'focus':
                obj.ClassList(evt.currentTarget).add("active");
                break;
            case 'blur':
                obj.ClassList(evt.currentTarget).remove("active");
                break;
            case 'click':
                evt.preventDefault();
                if ((obj.ClassList(evt.currentTarget).contains("cardslide-next"))) {
                    card_left -= 940;
                    if (card_left <= -presentation_width) {
                        card_left  = 0;
                    }
                    card_frame.style.left =  card_left+"px";
                }
                if ((obj.ClassList(evt.currentTarget).contains("cardslide-prev"))) {
                    if (card_left >= 0) {
                        card_left  = -presentation_width;
                    }
                    card_left += 940;
                    card_frame.style.left =  card_left+"px";
                }
                break;
            default:
                return;
            }
        };
        //
        // Add Event Listenrs
        aEventListener(tab1, 'mouseover', gestureEvent);
        aEventListener(tab1, 'mouseout', gestureEvent);
        aEventListener(tab2, 'mouseover', gestureEvent);
        aEventListener(tab2, 'mouseout', gestureEvent);
        aEventListener(sch, 'focus', gestureEvent, true);
        aEventListener(sch, 'blur', gestureEvent, true);

        if (  card_prev !== null) {
            card_next = cssSelector(".cardslide-next");
            card_frame = cssSelector(".resources-card").getElementsByTagName("ul")[0];
            presentation_width = parseInt(card_frame.style.width);
            aEventListener(card_prev, 'click', gestureEvent);
            aEventListener(card_next, 'click', gestureEvent);
        }

        //
        // Clear unuseful Dom Object
        tab1 = null;
        tab2 = null;
        sch = null;
        card_prev = null;
        card_next = null;
    });
}());

<commit_msg>Add the pag marker slide while the card slide<commit_after>(function () {
    var tmp = UtilityBuild(['dmUtil'],function(obj){
        "use strict";
        //
        // Dependencies
        var cssSelector = obj.doc.querySelector.bind(obj.doc)
        ,aEventListener = obj.EventUtility.aboutHandler.addListener
        //
        // Boolean Variables
        ,mouse_hover = false
        ,click_on = false
        ,id = 0
        //
        // Dom Element
        ,tab1 = cssSelector("#horizontal-nav .horizontal-nav-wrapper nav #tab3")
        ,tab2 = cssSelector("#horizontal-nav .horizontal-nav-wrapper nav #tab4")
        ,pan1 = cssSelector("#pannel3")
        ,pan2 = cssSelector("#pannel4")
        ,sch = cssSelector(".header-wrapper .search")
        ,card_prev = cssSelector(".cardslide-prev")
        ,card_next = null
        ,card_frame = null
        ,presentation_width = 0
        ,card_left = 0
        ,pag_markers = cssSelector('.pagination').getElementsByTagName("li")
        ,pag_markers_len = pag_markers.length
        ,pag_id = 0
        //
        // Animations Core function
        ,opacPan = function opacPan(delta) { panell.style.opacity = 1 * delta + ""; }
        ,endPan = function endPan() { panell.removeAttribute("style"); }
        ,animations = obj.AnimateObject(200,300,'quadratic',opacPan,endPan)
        ,panell = null
        //
        // Event Callback function
        ,gestureEvent = function gestureEvent(evt) {
            var subject = animations
            ,aria_attr = "";

            switch (evt.type) {
            case 'mouseover':
                if (!mouse_hover) {
                mouse_hover = true;
                obj.animatedFrame.cancel(id);
                evt.currentTarget.setAttribute("aria-expanded", "true");
                aria_attr = evt.currentTarget.getAttribute("aria-controls");
                if (aria_attr === 'pannel3') {
                    panell = pan1;
                } else if (aria_attr === 'pannel4') {
                    panell = pan2;
                }
                subject.startTimeCount();
                subject.timePassed = subject.getStartTime();
                id = obj.animatedFrame.request(subject.animate.bind(subject));
                }
                break;
            case 'mouseout':
                mouse_hover = false;
                evt.currentTarget.setAttribute("aria-expanded", "false");
                break;
            case 'focus':
                obj.ClassList(evt.currentTarget).add("active");
                break;
            case 'blur':
                obj.ClassList(evt.currentTarget).remove("active");
                break;
            case 'click':
                evt.preventDefault();
                if ((obj.ClassList(evt.currentTarget).contains("cardslide-next"))) {
                    card_left -= 940;
                    pag_id += 1;

                    if (card_left <= -presentation_width) {
                        card_left  = 0;
                    }

                    obj.ClassList(pag_markers[pag_id-1]).remove("active");

                    if (pag_id > pag_markers_len-1) {
                        pag_id = 0;
                    }

                    obj.ClassList(pag_markers[pag_id]).add("active");
                    card_frame.style.left =  card_left+"px";
                }
                if ((obj.ClassList(evt.currentTarget).contains("cardslide-prev"))) {
                    if (card_left >= 0) {
                        card_left  = -presentation_width;
                    }
                    card_left += 940;
                    obj.ClassList(pag_markers[pag_id]).remove("active");
                    pag_id -= 1;

                    if (pag_id < 0) {
                        pag_id = pag_markers_len -1;
                    }

                    obj.ClassList(pag_markers[pag_id]).add("active");

                    card_frame.style.left =  card_left+"px";
                }
                break;
            default:
                return;
            }
        };
        //
        // Add Event Listenrs
        aEventListener(tab1, 'mouseover', gestureEvent);
        aEventListener(tab1, 'mouseout', gestureEvent);
        aEventListener(tab2, 'mouseover', gestureEvent);
        aEventListener(tab2, 'mouseout', gestureEvent);
        aEventListener(sch, 'focus', gestureEvent, true);
        aEventListener(sch, 'blur', gestureEvent, true);

        if (card_prev !== null) {
            card_next = cssSelector(".cardslide-next");
            card_frame = cssSelector(".resources-card").getElementsByTagName("ul")[0];
            presentation_width = parseInt(card_frame.style.width);
            aEventListener(card_prev, 'click', gestureEvent);
            aEventListener(card_next, 'click', gestureEvent);
        }

        //
        // Clear unuseful Dom Object
        tab1 = null;
        tab2 = null;
        sch = null;
        card_prev = null;
        card_next = null;
    });
}());

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
	addComponent,
	removeComponent,
	watchComponent,
	updateQuery,
	setQueryOptions,
	setQueryListener,
} from '@appbaseio/reactivecore/lib/actions';
import {
	isEqual,
	checkValueChange,
	checkPropChange,
	checkSomePropChange,
	getClassName,
	pushToAndClause,
} from '@appbaseio/reactivecore/lib/utils/helper';
import types from '@appbaseio/reactivecore/lib/utils/types';
import Rheostat from 'rheostat/lib/Slider';

import HistogramContainer from './addons/HistogramContainer';
import RangeLabel from './addons/RangeLabel';
import SliderHandle from './addons/SliderHandle';
import Slider from '../../styles/Slider';
import Title from '../../styles/Title';
import { rangeLabelsContainer } from '../../styles/Label';
import { connect } from '../../utils';

class RangeSlider extends Component {
	constructor(props) {
		super(props);

		const { selectedValue, defaultValue, value } = props;
		const valueToParse = selectedValue || value || defaultValue;
		const currentValue = RangeSlider.parseValue(valueToParse, props);
		this.state = {
			currentValue,
			stats: [],
		};

		this.locked = false;
		this.internalComponent = `${this.props.componentId}__internal`;

		props.addComponent(props.componentId);
		props.addComponent(this.internalComponent);
		props.setQueryListener(props.componentId, props.onQueryChange, null);

		this.updateQueryOptions(props);
		this.setReact(props);
		const hasMounted = false;

		if (currentValue) {
			this.handleChange(currentValue, props, hasMounted);
		}
	}

	componentDidUpdate(prevProps) {
		checkPropChange(this.props.react, prevProps.react, () => this.setReact(this.props));
		checkSomePropChange(this.props, prevProps, ['showHistogram', 'interval'], () =>
			this.updateQueryOptions(this.props),
		);
		checkPropChange(this.props.options, prevProps.options, () => {
			const { options } = this.props;
			if (Array.isArray(options)) {
				options.sort((a, b) => {
					if (a.key < b.key) return -1;
					if (a.key > b.key) return 1;
					return 0;
				});
			}
			this.setState({
				stats: options || [],
			});
		});

		checkPropChange(this.props.dataField, prevProps.dataField, () => {
			this.updateQueryOptions(this.props);
			this.handleChange(this.state.currentValue, this.props);
		});

		if (!isEqual(this.props.value, prevProps.value)) {
			const value = RangeSlider.parseValue(this.props.value, this.props);
			this.handleChange(value, this.props);
		} else if (
			!isEqual(this.state.currentValue, this.props.selectedValue)
			&& !isEqual(this.props.selectedValue, prevProps.selectedValue)
		) {
			const value = RangeSlider.parseValue(this.props.selectedValue, this.props);
			this.handleChange(value, this.props);
		}
	}

	shouldComponentUpdate(nextProps) {
		const upperLimit = Math.floor((nextProps.range.end - nextProps.range.start) / 2);
		if (nextProps.stepValue < 1 || nextProps.stepValue > upperLimit) {
			console.warn(
				`stepValue for RangeSlider ${
					nextProps.componentId
				} should be greater than 0 and less than or equal to ${upperLimit}`,
			);
			return false;
		}
		return true;
	}

	componentWillUnmount() {
		this.props.removeComponent(this.props.componentId);
		this.props.removeComponent(this.internalComponent);
	}

	setReact = (props) => {
		const { react } = props;
		if (react) {
			const newReact = pushToAndClause(react, this.internalComponent);
			props.watchComponent(props.componentId, newReact);
		} else {
			props.watchComponent(props.componentId, {
				and: this.internalComponent,
			});
		}
	};

	static parseValue = (value, props) => {
		if (Array.isArray(value)) return value;
		return value ? [value.start, value.end] : [props.range.start, props.range.end];
	};

	static defaultQuery = (value, props) => {
		if (Array.isArray(value) && value.length) {
			return {
				range: {
					[props.dataField]: {
						gte: value[0],
						lte: value[1],
						boost: 2.0,
					},
				},
			};
		}
		return null;
	};

	getSnapPoints = () => {
		let snapPoints = [];
		let { stepValue } = this.props;

		// limit the number of steps to prevent generating a large number of snapPoints
		if ((this.props.range.end - this.props.range.start) / stepValue > 100) {
			stepValue = (this.props.range.end - this.props.range.start) / 100;
		}

		for (let i = this.props.range.start; i <= this.props.range.end; i += stepValue) {
			snapPoints = snapPoints.concat(i);
		}
		if (snapPoints[snapPoints.length - 1] !== this.props.range.end) {
			snapPoints = snapPoints.concat(this.props.range.end);
		}
		return snapPoints;
	};

	getValidInterval = (props) => {
		const min = Math.ceil((props.range.end - props.range.start) / 100) || 1;
		if (!props.interval) {
			return min;
		} else if (props.interval < min) {
			console.error(
				`${
					props.componentId
				}: interval prop's value should be greater than or equal to ${min}`,
			);
			return min;
		}
		return props.interval;
	};

	histogramQuery = props => ({
		[props.dataField]: {
			histogram: {
				field: props.dataField,
				interval: this.getValidInterval(props),
				offset: props.range.start,
			},
		},
	});

	handleChange = (currentValue, props = this.props, hasMounted = true) => {
		// ignore state updates when component is locked
		if (props.beforeValueChange && this.locked) {
			return;
		}

		this.locked = true;
		const performUpdate = () => {
			const handleUpdates = () => {
				const [start, end] = currentValue;
				this.updateQuery([start, end], props);
				this.locked = false;
				if (props.onValueChange) {
					props.onValueChange({
						start,
						end,
					});
				}
			};

			if (hasMounted) {
				this.setState(
					{
						currentValue,
					},
					handleUpdates,
				);
			} else {
				handleUpdates();
			}
		};
		checkValueChange(
			props.componentId,
			{
				start: currentValue[0],
				end: currentValue[1],
			},
			props.beforeValueChange,
			performUpdate,
		);
	};

	handleSlider = ({ values }) => {
		if (!isEqual(values, this.state.currentValue)) {
			const { value, onChange } = this.props;
			if (value) {
				if (onChange) {
					onChange(values);
				} else {
					// since value prop is set & onChange is not defined
					// we need to reset the slider position
					// to the original 'value' prop
					this.setState({
						currentValue: this.state.currentValue,
					});
				}
			} else {
				this.handleChange(values);
			}
		}
	};

	handleDrag = (values) => {
		if (this.props.onDrag) {
			const { min, max, values: currentValue } = values;
			this.props.onDrag(currentValue, [min, max]);
		}
	};

	updateQuery = (value, props) => {
		const query = props.customQuery || RangeSlider.defaultQuery;
		const {
			showFilter,
			range: { start, end },
		} = props;
		const [currentStart, currentEnd] = value;
		// check if the slider is at its initial position
		const isInitialValue = currentStart === start && currentEnd === end;
		props.updateQuery({
			componentId: props.componentId,
			query: query(value, props),
			value,
			label: props.filterLabel,
			showFilter: showFilter && !isInitialValue,
			URLParams: props.URLParams,
			componentType: 'RANGESLIDER',
		});
	};

	updateQueryOptions = (props) => {
		if (props.showHistogram) {
			const queryOptions = {
				size: 0,
				aggs: (props.histogramQuery || this.histogramQuery)(props),
			};

			props.setQueryOptions(this.internalComponent, queryOptions, false);

			const query = props.customQuery || RangeSlider.defaultQuery;

			props.updateQuery({
				componentId: this.internalComponent,
				query: query([props.range.start, props.range.end], props),
			});
		}
	};

	render() {
		return (
			<Slider primary style={this.props.style} className={this.props.className}>
				{this.props.title && (
					<Title className={getClassName(this.props.innerClass, 'title') || null}>
						{this.props.title}
					</Title>
				)}
				{this.state.stats.length && this.props.showHistogram && this.props.showSlider ? (
					<HistogramContainer
						stats={this.state.stats}
						range={this.props.range}
						interval={this.getValidInterval(this.props)}
					/>
				) : null}
				{this.props.showSlider && (
					<Rheostat
						min={this.props.range.start}
						max={this.props.range.end}
						values={this.state.currentValue}
						onChange={this.handleSlider}
						onValuesUpdated={this.handleDrag}
						snap={this.props.snap}
						snapPoints={this.props.snap ? this.getSnapPoints() : null}
						className={getClassName(this.props.innerClass, 'slider')}
						handle={({ className, style, ...passProps }) => (
							<SliderHandle
								style={style}
								className={className}
								{...passProps}
								renderTooltipData={this.props.renderTooltipData}
								tooltipTrigger={this.props.tooltipTrigger}
							/>
						)}
					/>
				)}
				{this.props.rangeLabels && this.props.showSlider && (
					<div className={rangeLabelsContainer}>
						<RangeLabel
							align="left"
							className={getClassName(this.props.innerClass, 'label') || null}
						>
							{this.props.rangeLabels.start}
						</RangeLabel>
						<RangeLabel
							align="right"
							className={getClassName(this.props.innerClass, 'label') || null}
						>
							{this.props.rangeLabels.end}
						</RangeLabel>
					</div>
				)}
			</Slider>
		);
	}
}

RangeSlider.propTypes = {
	addComponent: types.funcRequired,
	removeComponent: types.funcRequired,
	setQueryListener: types.funcRequired,
	setQueryOptions: types.funcRequired,
	updateQuery: types.funcRequired,
	watchComponent: types.funcRequired,
	options: types.options,
	selectedValue: types.selectedValue,
	// component props
	beforeValueChange: types.func,
	className: types.string,
	componentId: types.stringRequired,
	customQuery: types.func,
	dataField: types.stringRequired,
	defaultSelected: types.range,
	filterLabel: types.string,
	innerClass: types.style,
	interval: types.number,
	onDrag: types.func,
	onQueryChange: types.func,
	onValueChange: types.func,
	range: types.range,
	rangeLabels: types.rangeLabels,
	react: types.react,
	showHistogram: types.bool,
	histogramQuery: types.func,
	showFilter: types.bool,
	showSlider: types.bool,
	tooltipTrigger: types.tooltipTrigger,
	renderTooltipData: types.func,
	snap: types.bool,
	stepValue: types.number,
	style: types.style,
	title: types.title,
	URLParams: types.bool,
};

RangeSlider.defaultProps = {
	className: null,
	range: {
		start: 0,
		end: 10,
	},
	showHistogram: true,
	showSlider: true,
	tooltipTrigger: 'none',
	snap: true,
	stepValue: 1,
	showFilter: true,
	style: {},
	URLParams: false,
};

const mapStateToProps = (state, props) => ({
	options: state.aggregations[props.componentId]
		? state.aggregations[props.componentId][props.dataField]
		  && state.aggregations[props.componentId][props.dataField].buckets // eslint-disable-line
		: [],
	selectedValue: state.selectedValues[props.componentId]
		? state.selectedValues[props.componentId].value
		: null,
});

const mapDispatchtoProps = dispatch => ({
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	setQueryOptions: (component, props, execute) =>
		dispatch(setQueryOptions(component, props, execute)),
	setQueryListener: (component, onQueryChange, beforeQueryChange) =>
		dispatch(setQueryListener(component, onQueryChange, beforeQueryChange)),
	updateQuery: updateQueryObject => dispatch(updateQuery(updateQueryObject)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
});

export default connect(
	mapStateToProps,
	mapDispatchtoProps,
)(RangeSlider);
<commit_msg>web: update RangeSlider prop-types<commit_after>import React, { Component } from 'react';
import {
	addComponent,
	removeComponent,
	watchComponent,
	updateQuery,
	setQueryOptions,
	setQueryListener,
} from '@appbaseio/reactivecore/lib/actions';
import {
	isEqual,
	checkValueChange,
	checkPropChange,
	checkSomePropChange,
	getClassName,
	pushToAndClause,
} from '@appbaseio/reactivecore/lib/utils/helper';
import types from '@appbaseio/reactivecore/lib/utils/types';
import Rheostat from 'rheostat/lib/Slider';

import HistogramContainer from './addons/HistogramContainer';
import RangeLabel from './addons/RangeLabel';
import SliderHandle from './addons/SliderHandle';
import Slider from '../../styles/Slider';
import Title from '../../styles/Title';
import { rangeLabelsContainer } from '../../styles/Label';
import { connect } from '../../utils';

class RangeSlider extends Component {
	constructor(props) {
		super(props);

		const { selectedValue, defaultValue, value } = props;
		const valueToParse = selectedValue || value || defaultValue;
		const currentValue = RangeSlider.parseValue(valueToParse, props);
		this.state = {
			currentValue,
			stats: [],
		};

		this.locked = false;
		this.internalComponent = `${this.props.componentId}__internal`;

		props.addComponent(props.componentId);
		props.addComponent(this.internalComponent);
		props.setQueryListener(props.componentId, props.onQueryChange, null);

		this.updateQueryOptions(props);
		this.setReact(props);
		const hasMounted = false;

		if (currentValue) {
			this.handleChange(currentValue, props, hasMounted);
		}
	}

	componentDidUpdate(prevProps) {
		checkPropChange(this.props.react, prevProps.react, () => this.setReact(this.props));
		checkSomePropChange(this.props, prevProps, ['showHistogram', 'interval'], () =>
			this.updateQueryOptions(this.props),
		);
		checkPropChange(this.props.options, prevProps.options, () => {
			const { options } = this.props;
			if (Array.isArray(options)) {
				options.sort((a, b) => {
					if (a.key < b.key) return -1;
					if (a.key > b.key) return 1;
					return 0;
				});
			}
			this.setState({
				stats: options || [],
			});
		});

		checkPropChange(this.props.dataField, prevProps.dataField, () => {
			this.updateQueryOptions(this.props);
			this.handleChange(this.state.currentValue, this.props);
		});

		if (!isEqual(this.props.value, prevProps.value)) {
			const value = RangeSlider.parseValue(this.props.value, this.props);
			this.handleChange(value, this.props);
		} else if (
			!isEqual(this.state.currentValue, this.props.selectedValue)
			&& !isEqual(this.props.selectedValue, prevProps.selectedValue)
		) {
			const value = RangeSlider.parseValue(this.props.selectedValue, this.props);
			this.handleChange(value, this.props);
		}
	}

	shouldComponentUpdate(nextProps) {
		const upperLimit = Math.floor((nextProps.range.end - nextProps.range.start) / 2);
		if (nextProps.stepValue < 1 || nextProps.stepValue > upperLimit) {
			console.warn(
				`stepValue for RangeSlider ${
					nextProps.componentId
				} should be greater than 0 and less than or equal to ${upperLimit}`,
			);
			return false;
		}
		return true;
	}

	componentWillUnmount() {
		this.props.removeComponent(this.props.componentId);
		this.props.removeComponent(this.internalComponent);
	}

	setReact = (props) => {
		const { react } = props;
		if (react) {
			const newReact = pushToAndClause(react, this.internalComponent);
			props.watchComponent(props.componentId, newReact);
		} else {
			props.watchComponent(props.componentId, {
				and: this.internalComponent,
			});
		}
	};

	static parseValue = (value, props) => {
		if (Array.isArray(value)) return value;
		return value ? [value.start, value.end] : [props.range.start, props.range.end];
	};

	static defaultQuery = (value, props) => {
		if (Array.isArray(value) && value.length) {
			return {
				range: {
					[props.dataField]: {
						gte: value[0],
						lte: value[1],
						boost: 2.0,
					},
				},
			};
		}
		return null;
	};

	getSnapPoints = () => {
		let snapPoints = [];
		let { stepValue } = this.props;

		// limit the number of steps to prevent generating a large number of snapPoints
		if ((this.props.range.end - this.props.range.start) / stepValue > 100) {
			stepValue = (this.props.range.end - this.props.range.start) / 100;
		}

		for (let i = this.props.range.start; i <= this.props.range.end; i += stepValue) {
			snapPoints = snapPoints.concat(i);
		}
		if (snapPoints[snapPoints.length - 1] !== this.props.range.end) {
			snapPoints = snapPoints.concat(this.props.range.end);
		}
		return snapPoints;
	};

	getValidInterval = (props) => {
		const min = Math.ceil((props.range.end - props.range.start) / 100) || 1;
		if (!props.interval) {
			return min;
		} else if (props.interval < min) {
			console.error(
				`${
					props.componentId
				}: interval prop's value should be greater than or equal to ${min}`,
			);
			return min;
		}
		return props.interval;
	};

	histogramQuery = props => ({
		[props.dataField]: {
			histogram: {
				field: props.dataField,
				interval: this.getValidInterval(props),
				offset: props.range.start,
			},
		},
	});

	handleChange = (currentValue, props = this.props, hasMounted = true) => {
		// ignore state updates when component is locked
		if (props.beforeValueChange && this.locked) {
			return;
		}

		this.locked = true;
		const performUpdate = () => {
			const handleUpdates = () => {
				const [start, end] = currentValue;
				this.updateQuery([start, end], props);
				this.locked = false;
				if (props.onValueChange) {
					props.onValueChange({
						start,
						end,
					});
				}
			};

			if (hasMounted) {
				this.setState(
					{
						currentValue,
					},
					handleUpdates,
				);
			} else {
				handleUpdates();
			}
		};
		checkValueChange(
			props.componentId,
			{
				start: currentValue[0],
				end: currentValue[1],
			},
			props.beforeValueChange,
			performUpdate,
		);
	};

	handleSlider = ({ values }) => {
		if (!isEqual(values, this.state.currentValue)) {
			const { value, onChange } = this.props;
			if (value) {
				if (onChange) {
					onChange(values);
				} else {
					// since value prop is set & onChange is not defined
					// we need to reset the slider position
					// to the original 'value' prop
					this.setState({
						currentValue: this.state.currentValue,
					});
				}
			} else {
				this.handleChange(values);
			}
		}
	};

	handleDrag = (values) => {
		if (this.props.onDrag) {
			const { min, max, values: currentValue } = values;
			this.props.onDrag(currentValue, [min, max]);
		}
	};

	updateQuery = (value, props) => {
		const query = props.customQuery || RangeSlider.defaultQuery;
		const {
			showFilter,
			range: { start, end },
		} = props;
		const [currentStart, currentEnd] = value;
		// check if the slider is at its initial position
		const isInitialValue = currentStart === start && currentEnd === end;
		props.updateQuery({
			componentId: props.componentId,
			query: query(value, props),
			value,
			label: props.filterLabel,
			showFilter: showFilter && !isInitialValue,
			URLParams: props.URLParams,
			componentType: 'RANGESLIDER',
		});
	};

	updateQueryOptions = (props) => {
		if (props.showHistogram) {
			const queryOptions = {
				size: 0,
				aggs: (props.histogramQuery || this.histogramQuery)(props),
			};

			props.setQueryOptions(this.internalComponent, queryOptions, false);

			const query = props.customQuery || RangeSlider.defaultQuery;

			props.updateQuery({
				componentId: this.internalComponent,
				query: query([props.range.start, props.range.end], props),
			});
		}
	};

	render() {
		return (
			<Slider primary style={this.props.style} className={this.props.className}>
				{this.props.title && (
					<Title className={getClassName(this.props.innerClass, 'title') || null}>
						{this.props.title}
					</Title>
				)}
				{this.state.stats.length && this.props.showHistogram && this.props.showSlider ? (
					<HistogramContainer
						stats={this.state.stats}
						range={this.props.range}
						interval={this.getValidInterval(this.props)}
					/>
				) : null}
				{this.props.showSlider && (
					<Rheostat
						min={this.props.range.start}
						max={this.props.range.end}
						values={this.state.currentValue}
						onChange={this.handleSlider}
						onValuesUpdated={this.handleDrag}
						snap={this.props.snap}
						snapPoints={this.props.snap ? this.getSnapPoints() : null}
						className={getClassName(this.props.innerClass, 'slider')}
						handle={({ className, style, ...passProps }) => (
							<SliderHandle
								style={style}
								className={className}
								{...passProps}
								renderTooltipData={this.props.renderTooltipData}
								tooltipTrigger={this.props.tooltipTrigger}
							/>
						)}
					/>
				)}
				{this.props.rangeLabels && this.props.showSlider && (
					<div className={rangeLabelsContainer}>
						<RangeLabel
							align="left"
							className={getClassName(this.props.innerClass, 'label') || null}
						>
							{this.props.rangeLabels.start}
						</RangeLabel>
						<RangeLabel
							align="right"
							className={getClassName(this.props.innerClass, 'label') || null}
						>
							{this.props.rangeLabels.end}
						</RangeLabel>
					</div>
				)}
			</Slider>
		);
	}
}

RangeSlider.propTypes = {
	addComponent: types.funcRequired,
	removeComponent: types.funcRequired,
	setQueryListener: types.funcRequired,
	setQueryOptions: types.funcRequired,
	updateQuery: types.funcRequired,
	watchComponent: types.funcRequired,
	options: types.options,
	selectedValue: types.selectedValue,
	// component props
	beforeValueChange: types.func,
	className: types.string,
	componentId: types.stringRequired,
	customQuery: types.func,
	dataField: types.stringRequired,
	defaultValue: types.range,
	value: types.range,
	filterLabel: types.string,
	innerClass: types.style,
	interval: types.number,
	onDrag: types.func,
	onQueryChange: types.func,
	onValueChange: types.func,
	onChange: types.func,
	range: types.range,
	rangeLabels: types.rangeLabels,
	react: types.react,
	showHistogram: types.bool,
	histogramQuery: types.func,
	showFilter: types.bool,
	showSlider: types.bool,
	tooltipTrigger: types.tooltipTrigger,
	renderTooltipData: types.func,
	snap: types.bool,
	stepValue: types.number,
	style: types.style,
	title: types.title,
	URLParams: types.bool,
};

RangeSlider.defaultProps = {
	className: null,
	range: {
		start: 0,
		end: 10,
	},
	showHistogram: true,
	showSlider: true,
	tooltipTrigger: 'none',
	snap: true,
	stepValue: 1,
	showFilter: true,
	style: {},
	URLParams: false,
};

const mapStateToProps = (state, props) => ({
	options: state.aggregations[props.componentId]
		? state.aggregations[props.componentId][props.dataField]
		  && state.aggregations[props.componentId][props.dataField].buckets // eslint-disable-line
		: [],
	selectedValue: state.selectedValues[props.componentId]
		? state.selectedValues[props.componentId].value
		: null,
});

const mapDispatchtoProps = dispatch => ({
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	setQueryOptions: (component, props, execute) =>
		dispatch(setQueryOptions(component, props, execute)),
	setQueryListener: (component, onQueryChange, beforeQueryChange) =>
		dispatch(setQueryListener(component, onQueryChange, beforeQueryChange)),
	updateQuery: updateQueryObject => dispatch(updateQuery(updateQueryObject)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
});

export default connect(
	mapStateToProps,
	mapDispatchtoProps,
)(RangeSlider);
<|endoftext|>


<commit_before>module.exports = (function () {
    "use strict";

    var THREE = require("three"),
        TrackballControls = require("three.trackball");

    var Frame = function (elem, graph) {
        if (typeof elem === 'string') {
            elem = document.getElementById(elem);
        }

        if (graph._nodes.length < 2) {
            throw "A graph needs at least two nodes";
        }

        this.graph = graph;

        var width = elem.scrollWidth;
        var height = elem.scrollHeight;
        var aspectRatio = width/height;

        this._initScene();
        this._initRenderer(width, height, elem);
        this._initNodes(graph.getNodes());
        this._normalizeNodes();
        this._initEdges(graph.getEdges());

        this._initCamera(aspectRatio);
        this._initControls(elem);

        this.positionCamera();

        this._initMouseEvents(elem);

        this._animate();
    };

    Frame.prototype._initScene = function () {
        this.scene = new THREE.Scene();
    };

    Frame.prototype._initCamera = function (aspect) {
        var self = this;

        var viewAngle = this.graph._fov;
        var camera = new THREE.PerspectiveCamera(viewAngle, aspect);

        this.camera = camera;

        window.addEventListener('resize', function () {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            // TODO this should be the element width/height, not the window
            self.renderer.setSize(window.innerWidth, window.innerHeight);
            self.forceRerender();
        }, false);
    };

    Frame.prototype._initRenderer = function (width, height, elem) {
        var renderer = new THREE.WebGLRenderer({
            antialias: this.graph._antialias,
            alpha: true,
        });
        renderer.setClearColor(this.graph._bgColor, this.graph._bgOpacity);
        renderer.setSize(width, height);
        elem.appendChild(renderer.domElement);

        this.renderer = renderer;
    };

    Frame.prototype.forceRerender = function () {
        this.renderer.render(this.scene, this.camera);
    };

    Frame.prototype._initControls = function (elem) {
        var self = this;
        var controls = new TrackballControls(this.camera, elem);

        controls.addEventListener('change', function () {
            self.forceRerender();
        });

        this.controls = controls;
    };

    Frame.prototype.positionCamera = function () {
        // Calculate optimal camera position
        this.points.computeBoundingSphere();
        var sphere = this.points.boundingSphere;

        var optimalDistance = (
            sphere.radius * 1.5 / Math.tan(this.graph._fov / 2));

        this.camera.position.x = sphere.center.x + optimalDistance;
        this.camera.position.y = sphere.center.y;
        this.camera.position.z = sphere.center.z;

        this.controls.target = sphere.center.clone();
    };

    Frame.prototype._initNodes = function (nodes) {
        var self = this;

        var material = new THREE.PointCloudMaterial({
            size: this.graph._nodeSize,
            vertexColors: true,
            sizeAttenuation: this.graph._sizeAttenuation,
            depthWrite: false,
        });

        if (this.graph._nodeImage !== undefined) {
            var texture = THREE.ImageUtils.loadTexture(
                this.graph._nodeImage, undefined, function () {
                    // Force a rerender after node image has finished loading
                    self.forceRerender();
                });
            material.map = texture;
        }

        var positions = new Float32Array(nodes.length * 3);
        var colors = new Float32Array(nodes.length * 3);
        for (var i = 0; i < nodes.length; i++) {
            var node = nodes[i];
            var pos = node._pos;
            var color = node._color;

            positions[3 * i] = pos.x;
            positions[3 * i + 1] = pos.y;
            positions[3 * i + 2] = pos.z;

            colors[3 * i] = color.r;
            colors[3 * i + 1] = color.g;
            colors[3 * i + 2] = color.b;
        }
        this.points = new THREE.BufferGeometry();
        this.points.addAttribute(
            'position', new THREE.BufferAttribute(positions, 3));
        this.points.addAttribute(
            'color', new THREE.BufferAttribute(colors, 3));

        this.pointCloud = new THREE.PointCloud(this.points, material);

        if (this.graph._nodeImageTransparent === true) {
            material.transparent = true;
            this.pointCloud.sortParticles = true;
        }

        this.scene.add(this.pointCloud);
    };

    Frame.prototype._normalizeNodes = function () {
        this.points.computeBoundingSphere();

        this.scale = 1 / this.points.boundingSphere.radius;
        var positions = this.points.attributes.position.array;

        for (var i = 0; i < positions.length; i++) {
            positions[i] *= this.scale;
        }
    };

    Frame.prototype._initEdges = function (edges) {
        var material = new THREE.LineBasicMaterial({
            vertexColors: true,
            linewidth: this.graph._edgeWidth,
            opacity: this.graph._edgeOpacity,
            transparent: this.graph._edgeOpacity < 1,
        });

        var positions = new Float32Array(edges.length * 6);
        var colors = new Float32Array(edges.length * 6);
        for (var i = 0; i < edges.length; i++) {
            var nodes = edges[i].getNodes();

            positions[3 * i] =     this.scale * nodes[0]._pos.x;
            positions[3 * i + 1] = this.scale * nodes[0]._pos.y;
            positions[3 * i + 2] = this.scale * nodes[0]._pos.z;

            positions[3 * i + 3] = this.scale * nodes[1]._pos.x;
            positions[3 * i + 4] = this.scale * nodes[1]._pos.y;
            positions[3 * i + 5] = this.scale * nodes[1]._pos.z;

            colors[3 * i] = colors[3 * i + 3] = edges[i]._color.r;
            colors[3 * i + 1] = colors[3 * i + 4] = edges[i]._color.g;
            colors[3 * i + 2] = colors[3 * i + 5] = edges[i]._color.b;
        }

        this.edges = new THREE.BufferGeometry();
        this.edges.addAttribute(
            'position', new THREE.BufferAttribute(positions, 3));
        this.edges.addAttribute(
            'color', new THREE.BufferAttribute(colors, 3));

        this.line = new THREE.Line(this.edges, material, THREE.LinePieces);
        this.scene.add(this.line);
    };

    Frame.prototype._initMouseEvents = function (elem) {
        var self = this;
        var createMouseHandler = function (callback) {
            var raycaster = new THREE.Raycaster();

            return function (evt) {
                evt.preventDefault();

                var mouseX = (evt.clientX / window.innerWidth) * 2 - 1;
                var mouseY = 1 - (evt.clientY / window.innerHeight) * 2;

                // Calculate mouse position
                var mousePosition = new THREE.Vector3(mouseX, mouseY, 0.1);
                var radiusPosition = mousePosition.clone();
                mousePosition.unproject(self.camera);

                // Calculate threshold
                var clickRadiusPx = 5;  // 5px
                var radiusX = ((evt.clientX + clickRadiusPx) / window.innerWidth) * 2 - 1;
                radiusPosition.setX(radiusX);
                radiusPosition.unproject(self.camera);

                var clickRadius = radiusPosition.distanceTo(mousePosition);
                var threshold = (
                    self.camera.far * clickRadius / self.camera.near);

                raycaster.params.PointCloud.threshold = threshold;

                // Determine intersects
                raycaster.set(self.camera.position, mousePosition.sub(self.camera.position).normalize());
                var intersects = raycaster.intersectObject(self.pointCloud);
                if (intersects.length) {
                    var nodeIndex = intersects[0].index;
                    callback(self.graph._nodes[nodeIndex]);
                }
            };
        };

        if (this.graph._hover) {
            elem.addEventListener(
                'mousemove', createMouseHandler(this.graph._hover), false);
        }

        if (this.graph._click) {
            elem.addEventListener('click', createMouseHandler(this.graph._click), false);
        }
    };

    Frame.prototype._updateCameraBounds = (function () {
        var prevCameraPos;
        return function () {
            // TODO: this shouldn't update every frame
            // TODO: is this still even necessary now that we scale?
            var cameraPos = this.camera.position;

            if (cameraPos === prevCameraPos) { return; }

            var boundingSphere = this.points.boundingSphere;
            var distance = boundingSphere.distanceToPoint(cameraPos);

            if (distance > 0) {
                this.camera.near = distance;
                this.camera.far = distance + boundingSphere.radius * 2;
                this.camera.updateProjectionMatrix();
            }

            prevCameraPos = cameraPos.clone();
        };
    }());

    Frame.prototype._animate = function () {
        var self = this;

        // Update near/far camera range
        (function animate() {
            self._updateCameraBounds();

            window.requestAnimationFrame(animate);
            self.controls.update();
        }());
    };

    return Frame;
}());
<commit_msg>Wrap long lines<commit_after>module.exports = (function () {
    "use strict";

    var THREE = require("three"),
        TrackballControls = require("three.trackball");

    var Frame = function (elem, graph) {
        if (typeof elem === 'string') {
            elem = document.getElementById(elem);
        }

        if (graph._nodes.length < 2) {
            throw "A graph needs at least two nodes";
        }

        this.graph = graph;

        var width = elem.scrollWidth;
        var height = elem.scrollHeight;
        var aspectRatio = width/height;

        this._initScene();
        this._initRenderer(width, height, elem);
        this._initNodes(graph.getNodes());
        this._normalizeNodes();
        this._initEdges(graph.getEdges());

        this._initCamera(aspectRatio);
        this._initControls(elem);

        this.positionCamera();

        this._initMouseEvents(elem);

        this._animate();
    };

    Frame.prototype._initScene = function () {
        this.scene = new THREE.Scene();
    };

    Frame.prototype._initCamera = function (aspect) {
        var self = this;

        var viewAngle = this.graph._fov;
        var camera = new THREE.PerspectiveCamera(viewAngle, aspect);

        this.camera = camera;

        window.addEventListener('resize', function () {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            // TODO this should be the element width/height, not the window
            self.renderer.setSize(window.innerWidth, window.innerHeight);
            self.forceRerender();
        }, false);
    };

    Frame.prototype._initRenderer = function (width, height, elem) {
        var renderer = new THREE.WebGLRenderer({
            antialias: this.graph._antialias,
            alpha: true,
        });
        renderer.setClearColor(this.graph._bgColor, this.graph._bgOpacity);
        renderer.setSize(width, height);
        elem.appendChild(renderer.domElement);

        this.renderer = renderer;
    };

    Frame.prototype.forceRerender = function () {
        this.renderer.render(this.scene, this.camera);
    };

    Frame.prototype._initControls = function (elem) {
        var self = this;
        var controls = new TrackballControls(this.camera, elem);

        controls.addEventListener('change', function () {
            self.forceRerender();
        });

        this.controls = controls;
    };

    Frame.prototype.positionCamera = function () {
        // Calculate optimal camera position
        this.points.computeBoundingSphere();
        var sphere = this.points.boundingSphere;

        var optimalDistance = (
            sphere.radius * 1.5 / Math.tan(this.graph._fov / 2));

        this.camera.position.x = sphere.center.x + optimalDistance;
        this.camera.position.y = sphere.center.y;
        this.camera.position.z = sphere.center.z;

        this.controls.target = sphere.center.clone();
    };

    Frame.prototype._initNodes = function (nodes) {
        var self = this;

        var material = new THREE.PointCloudMaterial({
            size: this.graph._nodeSize,
            vertexColors: true,
            sizeAttenuation: this.graph._sizeAttenuation,
            depthWrite: false,
        });

        if (this.graph._nodeImage !== undefined) {
            var texture = THREE.ImageUtils.loadTexture(
                this.graph._nodeImage, undefined, function () {
                    // Force a rerender after node image has finished loading
                    self.forceRerender();
                });
            material.map = texture;
        }

        var positions = new Float32Array(nodes.length * 3);
        var colors = new Float32Array(nodes.length * 3);
        for (var i = 0; i < nodes.length; i++) {
            var node = nodes[i];
            var pos = node._pos;
            var color = node._color;

            positions[3 * i] = pos.x;
            positions[3 * i + 1] = pos.y;
            positions[3 * i + 2] = pos.z;

            colors[3 * i] = color.r;
            colors[3 * i + 1] = color.g;
            colors[3 * i + 2] = color.b;
        }
        this.points = new THREE.BufferGeometry();
        this.points.addAttribute(
            'position', new THREE.BufferAttribute(positions, 3));
        this.points.addAttribute(
            'color', new THREE.BufferAttribute(colors, 3));

        this.pointCloud = new THREE.PointCloud(this.points, material);

        if (this.graph._nodeImageTransparent === true) {
            material.transparent = true;
            this.pointCloud.sortParticles = true;
        }

        this.scene.add(this.pointCloud);
    };

    Frame.prototype._normalizeNodes = function () {
        this.points.computeBoundingSphere();

        this.scale = 1 / this.points.boundingSphere.radius;
        var positions = this.points.attributes.position.array;

        for (var i = 0; i < positions.length; i++) {
            positions[i] *= this.scale;
        }
    };

    Frame.prototype._initEdges = function (edges) {
        var material = new THREE.LineBasicMaterial({
            vertexColors: true,
            linewidth: this.graph._edgeWidth,
            opacity: this.graph._edgeOpacity,
            transparent: this.graph._edgeOpacity < 1,
        });

        var positions = new Float32Array(edges.length * 6);
        var colors = new Float32Array(edges.length * 6);
        for (var i = 0; i < edges.length; i++) {
            var nodes = edges[i].getNodes();

            positions[3 * i] =     this.scale * nodes[0]._pos.x;
            positions[3 * i + 1] = this.scale * nodes[0]._pos.y;
            positions[3 * i + 2] = this.scale * nodes[0]._pos.z;

            positions[3 * i + 3] = this.scale * nodes[1]._pos.x;
            positions[3 * i + 4] = this.scale * nodes[1]._pos.y;
            positions[3 * i + 5] = this.scale * nodes[1]._pos.z;

            colors[3 * i] = colors[3 * i + 3] = edges[i]._color.r;
            colors[3 * i + 1] = colors[3 * i + 4] = edges[i]._color.g;
            colors[3 * i + 2] = colors[3 * i + 5] = edges[i]._color.b;
        }

        this.edges = new THREE.BufferGeometry();
        this.edges.addAttribute(
            'position', new THREE.BufferAttribute(positions, 3));
        this.edges.addAttribute(
            'color', new THREE.BufferAttribute(colors, 3));

        this.line = new THREE.Line(this.edges, material, THREE.LinePieces);
        this.scene.add(this.line);
    };

    Frame.prototype._initMouseEvents = function (elem) {
        var self = this;
        var createMouseHandler = function (callback) {
            var raycaster = new THREE.Raycaster();

            return function (evt) {
                evt.preventDefault();

                var mouseX = (evt.clientX / window.innerWidth) * 2 - 1;
                var mouseY = 1 - (evt.clientY / window.innerHeight) * 2;

                // Calculate mouse position
                var mousePosition = new THREE.Vector3(mouseX, mouseY, 0.1);
                var radiusPosition = mousePosition.clone();
                mousePosition.unproject(self.camera);

                // Calculate threshold
                var clickRadiusPx = 5;  // 5px
                var radiusX = ((evt.clientX + clickRadiusPx) / window.innerWidth) * 2 - 1;
                radiusPosition.setX(radiusX);
                radiusPosition.unproject(self.camera);

                var clickRadius = radiusPosition.distanceTo(mousePosition);
                var threshold = (
                    self.camera.far * clickRadius / self.camera.near);

                raycaster.params.PointCloud.threshold = threshold;

                // Determine intersects
                var mouseDirection = (
                    mousePosition.sub(self.camera.position).normalize());
                raycaster.set(self.camera.position, mouseDirection);
                var intersects = raycaster.intersectObject(self.pointCloud);
                if (intersects.length) {
                    var nodeIndex = intersects[0].index;
                    callback(self.graph._nodes[nodeIndex]);
                }
            };
        };

        if (this.graph._hover) {
            elem.addEventListener(
                'mousemove', createMouseHandler(this.graph._hover), false);
        }

        if (this.graph._click) {
            elem.addEventListener(
                'click', createMouseHandler(this.graph._click), false);
        }
    };

    Frame.prototype._updateCameraBounds = (function () {
        var prevCameraPos;
        return function () {
            // TODO: this shouldn't update every frame
            // TODO: is this still even necessary now that we scale?
            var cameraPos = this.camera.position;

            if (cameraPos === prevCameraPos) { return; }

            var boundingSphere = this.points.boundingSphere;
            var distance = boundingSphere.distanceToPoint(cameraPos);

            if (distance > 0) {
                this.camera.near = distance;
                this.camera.far = distance + boundingSphere.radius * 2;
                this.camera.updateProjectionMatrix();
            }

            prevCameraPos = cameraPos.clone();
        };
    }());

    Frame.prototype._animate = function () {
        var self = this;

        // Update near/far camera range
        (function animate() {
            self._updateCameraBounds();

            window.requestAnimationFrame(animate);
            self.controls.update();
        }());
    };

    return Frame;
}());
<|endoftext|>


<commit_before>// Initiate the main screen of the vocabulary browser
// The first thing to be displayed is always the root category
(function(){  // $target refers to the div on screen where the concept will be displayed
    var $target = $(document.createElement("div"));

    var prefix = "/plugins/vb";
    var selected = { leaves:[], folders:[]};

    // Make sure the currently displayed nodes are correctly colored
       // as to whether they are selected for the query.
    var refreshBrowser = function(){
        $target.find("#browser_list li").removeClass("added");
        $target.find("#browser_list li input").attr("disabled","");

        $target.find("#results li").removeClass("added");
        $target.find("#results li input").attr("disabled","");

        $target.find("#browser_list li").add("#results li").each(function(index, element){
           element = $(element);
           if (element.data('node').child_ref){
               if ($.inArray(element.data('node').id, selected.folders) !=-1){
                   element.addClass("added");
                   element.find("input").attr("disabled","disabled");
               }

           } else{
               if ($.inArray(element.data('node').id,selected.leaves) !=-1){
                    element.addClass("added");
                    element.find("input").attr("disabled","disabled");
               }
           }
        });
    };

    // Remove a previously selected node..
    var removeNode = function($node){
        var index;
        if ($node.data("node").child_ref){
            index = $.inArray($node.data("node").id,selected.folders);
            selected.folders.splice(index,1);
        }else{
            index = $.inArray($node.data("node").id,selected.leaves);
            selected.leaves.splice(index,1);
        }
        $node.remove();
        refreshBrowser();
    };

    // This function will use the "selected" object to create
    // the tree structure that the Avocado state framework expects
    var addNode = function(node){
       var folder = false;
       if (node.child_ref){
           folder = true;
       }
       var $new_node = $('
<input type="button" value="-" class="button-remove"/>'+node.name+'
');
       $new_node.find("input").click(function(){
          $(this).trigger("removeItemEvent");
       });

       $new_node.data('node',node);
       $new_node.bind("removeItemEvent", function(){
            removeNode($(this));
            return false;
       });

       if (folder){
           if ($.inArray(node.id,selected.folders)!=-1){
               return;
           }
           $target.find("#members").prepend($new_node);
           selected.folders.unshift(node.id);
       }else{
            if ($.inArray(node.id, selected.leaves)!=-1){
                  return;
            }
            $target.find("#members").prepend($new_node);
            selected.leaves.unshift(node.id);
       }

    };

    var reloadBrowser = function(category){
       $.get(prefix+'/browse/'+category.replace("#",""), function(data){
               data = $.parseJSON(data);
               $target.find("#browser_list").empty();
               for (var index = 0; index < data.nodes.length; index++) {
                   var $li = $($("#browse-template").jqote(data.nodes[index]));
                   $li.data("node",data.nodes[index]);

                   // Check to see if the item has been selected
                   if (data.nodes[index].child_ref){
                       if ($.inArray(data.nodes[index].id, selected.folders)!=-1){
                           $li.addClass("added");
                       }
                   }else{
                        if ($.inArray(data.nodes[index].id, selected.leaves)!=-1){
                              $li.addClass("added");
                        }
                   }

                   $("#browser_list").append($li);
                   $li.bind("addItemEvent", function(evt){
                       addNode($(this).data("node"));
                       $(this).addClass("added");
                       return false;
                   });
                   $li.bind("descendEvent", function(){
                       reloadBrowser("#"+$(this).data("node").child_ref);
                       return false;
                   });
                   $li.filter(".folder").click(function(){
                       $(this).trigger("descendEvent");
                   });

                   $li.filter(".folder").hover(function(){
                      $(this).addClass("list_on");
                   }, function(){

                      $(this).removeClass("list_on");
                   });

               }
               $target.find('.button-add').click(function(evt){
                   $(this).trigger("addItemEvent");
                   $(this).attr("disabled", "disabled");
                   return false;
               });

               $target.find('.button-descend').click(function(evt){
                    $(this).trigger("descendEvent");
                    return false;
               });

               $target.find('#nav').empty().html($("#breadcrumbs-template").jqote(data));
               $target.find('#nav div.breadcrumb').bind("click", function(){
                   reloadBrowser("#"+$(this).attr("catid"));
                   return false;
               });
               $target.find('#nav div.breadcrumb').hover(function(){
                   $(this).addClass("hovercrumbs");

               }, function(){
                   $(this).removeClass("hovercrumbs");
               });

               $target.find('#button-back').button({text:false,icons:{primary:'ui-icon-arrowthick-1-w'}});
               $target.find('#button-back').click(function(evt){
                   if (data.path.length == 1) {
                       reloadBrowser("#");
                   }else{
                       reloadBrowser("#"+data.path[data.path.length-2].child_ref);
                   }
               });
       }, "json", function(settings){
           if (settings.url === (prefix+"/browse/")) {
              return $.parseJSON($.ajax({ type: "GET", url: "/static/fixtures/root.json", async: false, dataType:"json" }).responseText);
           } else {
              return $.parseJSON($.ajax({ type: "GET", url: "/static/fixtures/notroot.json", async: false, dataType:"json" }).responseText);
           }
       });
    };

    // We need to inject our templates into the application, at this point we are assuming that our jqote templates
    // are being delivered by the django template system
    $target.append($("#vocabulary_browser").jqote({browsertype:"Diagnoses"}));
    $target.addClass("container cf");

    var $receiver = $target.find("#results");
    var $input = $target.find("#vocab_search");

    // enable tabs, we use a very barebones tabs implementation
    // the core code only adds the appropriate classes to selected
    // and non-selected tabs, represented by  elements.
    $target.find('.tabs').tabs(false, function (evt, $tab){
        refreshBrowser();
        var $siblings = $tab.siblings('.tab');
        $($tab.attr('hash')).show();
        $siblings.each(function(index, neighbor){
            $($(neighbor).attr('hash')).hide();
        });
    });

    // Setup the browser
    reloadBrowser("");

    // Hijacking all links that contain an href
    // $target.find('a[href]:not(.tab)').live("click", function(){
    //     reloadBrowser(this.hash);
    //     $("#showBrowse").trigger("click");
    //     return false;
    // });

    // Setup the search
    $target.find("#vocab_search").autocomplete({
        fixture:"/static/fixtures/search_results.json",
        start: function() {
            $input.removeClass("searchIdle").addClass("searchAjax");
        },
        success: function(query, resp) {
            $input.removeClass("searchAjax").addClass("searchIdle");
            $receiver.empty();
            $.each(resp, function(index, value){
                if (value.id === -1) {
                      $receiver.append("
No matches.
");
                      return;
                }
                var $li=$($("#results_template").jqote(value));
                $li.data("node",value);
                $li.find(".path_node").hover(function(){$(this).addClass("over");},
                                             function(){$(this).removeClass("over");});
                $li.find(".path_node").each(function(index,element){

                   $(element).click(function(evt){
                       reloadBrowser("#" + value.path[parseInt($(evt.target).attr("pathid"))].id);
                       $("#showBrowse").trigger("click");
                       return false;
                   });

                });

                if (value.child_ref){
                     if ($.inArray(value.id, selected.folders)!=-1){
                         $li.addClass("added");
                     }
                }else{
                      if ($.inArray(value.id, selected.leaves)!=-1){
                        $li.addClass("added");
                      }
                }

                $li.filter(".folder").hover(function(){
                   $(this).addClass("list_on");
                }, function(){
                   $(this).removeClass("list_on");
                });
                $li.bind("addItemEvent",function(){
                    addNode($(this).data("node"));
                    $(this).addClass("added");
                    return false;
                });
                $li.hover(function(){
                     $(this).addClass("list_on");
                  }, function(){

                     $(this).removeClass("list_on");
                  });
                $li.click(function(){
                   var info = $(this).data("node");
                   if (info.child_ref){
                       reloadBrowser("#"+info.id);
                   }else if (info.path){
                       reloadBrowser("#"+info.path[info.path.length-1].id);
                   }else{
                       reloadBrowser("");
                   }
                $("#showBrowse").trigger("click");
                   return false;
                });

                $receiver.append($li);
            });

            $receiver.find(".button-add").click(function(){
                $(this).trigger("addItemEvent");
                $(this).attr("disabled", "disabled");
                return false;
            });
        },
        error: function(){
            $input.removeClass("searchAjax").addClass("searchIdle");
        }
    }, 'Search criteria...').helptext('Search criteria...');

    $target.find("#add-to-query").click(function(){
          var tree =  [{
                        'type': 'logic',
                        'operator': 'or',
                        'children': [{
                            'type': 'field',
                            'id': 1,
                            'operator': 'in',
                            'value': selected.leaves
                        }, {
                            'type': 'field',
                            'id': 2,
                            'operator': 'in',
                            'value': selected.folders
                        }]
                      }];
           $target.trigger("queryEvent", tree);
           console.log(tree);
       });
    $("body").trigger("widgetLoadedEvent", $target);
})();<commit_msg>Moved templates to the javascript file for now.<commit_after>// Initiate the main screen of the vocabulary browser
// The first thing to be displayed is always the root category
(function(){  // $target refers to the div on screen where the concept will be displayed
    var $target = $(document.createElement("div"));
    var prefix = "/plugins/vb";
    var selected = { leaves:[], folders:[]};

    var breadcrumbsTemplate = [
    '<% if (this.path.length===0) {%>',
    '<input type="button" style="visibility:hidden;" id="button-back" class="button-back" value="Back"/>Diagnoses',
    '<%} else { %>',
    '<input type="button" id="button-back" class="button-back" value="Back"/>
Diagnoses
',
    '<% } %>',
    '<% for (var index = 0; index < this.path.length; index+=1) {%>',
    '   <% if (index === (this.path.length-1)) {%>',
    '» <%=this.path[index].name%>',
    '   <% } else { %>',
    '» <div class="breadcrumb" catid="<%=this.path[index].child_ref%>"><%=this.path[index].name%>
',
    '   <% } %>',
    '<% } %>'].join("");

    var browseTemplate = [
    '<% if (this.child_ref) { %>',
    '
',
    '
',
    '<input type="button" class="button-add" value = "+"/>',
    '
',
    '
',
    '
',
    '<%=this.name%>',
    '
',
    '
',
    '
',
    '<% } else { %>',
    '
',
    '
',
    '<input type="button" class="button-add" value = "+"/>',
    '
',
    '
',
    '
',
    '<%=this.name%>',
    '
',
    '
',
    '<% if (this.attributes.icd9) { %>',
    'ICD-9 : <%=this.attributes.icd9%>',
    '<% } %>',
    '<% if (this.attributes.clinibase) { %>',
    'Clinibase ID : <%=this.attributes.clinibase%>',
    '<% } %>',
    '
',
    '
',
    '
',
    '

',
    '<% } %>'].join('');

    var searchResultsTemplate = [
    '
',
    '
',
    '<% if (this.child_ref) {%>',
    '<input type="button" value="+" class="button-add folder" id="folder<%=this.id%>"/>',
    '<% } else {%>',
    '<input type="button" value="+" class="button-add leaf" id="leaf<%=this.id%>"/>',
    '<%}%>',
    '
',
    '
',
    '
',
    '<% if (this.child_ref) { %>',
    '<%=this.name%>',
    '<% } else { %>',
    '<%=this.name%>',
    '<% } %>',
    '
',
    '
',
    '<% if (this.attributes.icd9) { %>',
    'ICD-9 : <%=this.attributes.icd9%>',
    '<% } %>',
    '<% if (this.attributes.clinibase) { %>',
    'Clinibase ID : <%=this.attributes.clinibase%>',
    '<% } %>',
    '
',
    '
',
    '<% for (index = 0; index < this.path.length; index++){ %>',
    '<div pathid="<%=index%>" class="path_node" style="display:inline;"><%=this.path[index].name%>
',
    '<% if (index != this.path.length -1){%> &raquo <%}%>',
    '<% } %>',
    '
',
    '
',
    '
',
    '

',
    ].join('');

    var vocabBrowserTemplate = [
    '
',
    '    <%= this.browsertype %> Browser',
    '
',
    '
',
    '    Browse Diagnoses',
    '    Search Diagnoses',
    '
',
    '
',
    '
',
    '

',
    '

',
    '
',
    '
',
    '         <form method="get" action="/plugins/vb/search">',
    '             <input type="text" class="searchIdle" id="vocab_search" name="term" size="50"/>',
    '         </form>',
    '
',
    '
',
    '
',
    '
',
    '
',
    '
',
    '
Patient has been diagnosed with:
',
    '

',
    '     <input type="button" id="add-to-query" value="Add to Query"/>',
    '
'
    ].join('');

    // Make sure the currently displayed nodes are correctly colored
    // as to whether they are selected for the query.
    var refreshBrowser = function(){
        $target.find("#browser_list li").removeClass("added");
        $target.find("#browser_list li input").attr("disabled","");

        $target.find("#results li").removeClass("added");
        $target.find("#results li input").attr("disabled","");

        $target.find("#browser_list li").add("#results li").each(function(index, element){
           element = $(element);
           if (element.data('node').child_ref){
               if ($.inArray(element.data('node').id, selected.folders) !=-1){
                   element.addClass("added");
                   element.find("input").attr("disabled","disabled");
               }

           } else{
               if ($.inArray(element.data('node').id,selected.leaves) !=-1){
                    element.addClass("added");
                    element.find("input").attr("disabled","disabled");
               }
           }
        });
    };

    // Remove a previously selected node..
    var removeNode = function($node){
        var index;
        if ($node.data("node").child_ref){
            index = $.inArray($node.data("node").id,selected.folders);
            selected.folders.splice(index,1);
        }else{
            index = $.inArray($node.data("node").id,selected.leaves);
            selected.leaves.splice(index,1);
        }
        $node.remove();
        refreshBrowser();
    };

    // This function will use the "selected" object to create
    // the tree structure that the Avocado state framework expects
    var addNode = function(node){
       var folder = false;
       if (node.child_ref){
           folder = true;
       }
       var $new_node = $('
<input type="button" value="-" class="button-remove"/>'+node.name+'
');
       $new_node.find("input").click(function(){
          $(this).trigger("removeItemEvent");
       });

       $new_node.data('node',node);
       $new_node.bind("removeItemEvent", function(){
            removeNode($(this));
            return false;
       });

       if (folder){
           if ($.inArray(node.id,selected.folders)!=-1){
               return;
           }
           $target.find("#members").prepend($new_node);
           selected.folders.unshift(node.id);
       }else{
            if ($.inArray(node.id, selected.leaves)!=-1){
                  return;
            }
            $target.find("#members").prepend($new_node);
            selected.leaves.unshift(node.id);
       }

    };

    var reloadBrowser = function(category){
       $.get(prefix+'/browse/'+category.replace("#",""), function(data){
               data = $.parseJSON(data);
               $target.find("#browser_list").empty();
               for (var index = 0; index < data.nodes.length; index++) {
                   var $li = $($.jqote(browseTemplate,data.nodes[index]));
                   $li.data("node",data.nodes[index]);

                   // Check to see if the item has been selected
                   if (data.nodes[index].child_ref){
                       if ($.inArray(data.nodes[index].id, selected.folders)!=-1){
                           $li.addClass("added");
                       }
                   }else{
                        if ($.inArray(data.nodes[index].id, selected.leaves)!=-1){
                              $li.addClass("added");
                        }
                   }

                   $("#browser_list").append($li);
                   $li.bind("addItemEvent", function(evt){
                       addNode($(this).data("node"));
                       $(this).addClass("added");
                       return false;
                   });
                   $li.bind("descendEvent", function(){
                       reloadBrowser("#"+$(this).data("node").child_ref);
                       return false;
                   });
                   $li.filter(".folder").click(function(){
                       $(this).trigger("descendEvent");
                   });

                   $li.filter(".folder").hover(function(){
                      $(this).addClass("list_on");
                   }, function(){

                      $(this).removeClass("list_on");
                   });

               }
               $target.find('.button-add').click(function(evt){
                   $(this).trigger("addItemEvent");
                   $(this).attr("disabled", "disabled");
                   return false;
               });

               $target.find('.button-descend').click(function(evt){
                    $(this).trigger("descendEvent");
                    return false;
               });

               $target.find('#nav').empty().html($.jqote(breadcrumbsTemplate,data));
               $target.find('#nav div.breadcrumb').bind("click", function(){
                   reloadBrowser("#"+$(this).attr("catid"));
                   return false;
               });
               $target.find('#nav div.breadcrumb').hover(function(){
                   $(this).addClass("hovercrumbs");

               }, function(){
                   $(this).removeClass("hovercrumbs");
               });

               $target.find('#button-back').button({text:false,icons:{primary:'ui-icon-arrowthick-1-w'}});
               $target.find('#button-back').click(function(evt){
                   if (data.path.length == 1) {
                       reloadBrowser("#");
                   }else{
                       reloadBrowser("#"+data.path[data.path.length-2].child_ref);
                   }
               });
       }, "json", function(settings){
           if (settings.url === (prefix+"/browse/")) {
              return $.parseJSON($.ajax({ type: "GET", url: "/static/fixtures/root.json", async: false, dataType:"json" }).responseText);
           } else {
              return $.parseJSON($.ajax({ type: "GET", url: "/static/fixtures/notroot.json", async: false, dataType:"json" }).responseText);
           }
       });
    };

    // We need to inject our templates into the application, at this point we are assuming that our jqote templates
    // are being delivered by the django template system
    $target.append($.jqote(vocabBrowserTemplate,{browsertype:"Diagnoses"}));
    $target.addClass("container cf");

    var $receiver = $target.find("#results");
    var $input = $target.find("#vocab_search");

    // enable tabs, we use a very barebones tabs implementation
    // the core code only adds the appropriate classes to selected
    // and non-selected tabs, represented by  elements.
    $target.find('.tabs').tabs(false, function (evt, $tab){
        refreshBrowser();
        var $siblings = $tab.siblings('.tab');
        $($tab.attr('hash')).show();
        $siblings.each(function(index, neighbor){
            $($(neighbor).attr('hash')).hide();
        });
    });

    // Setup the browser
    reloadBrowser("");

    // Hijacking all links that contain an href
    // $target.find('a[href]:not(.tab)').live("click", function(){
    //     reloadBrowser(this.hash);
    //     $("#showBrowse").trigger("click");
    //     return false;
    // });

    // Setup the search
    $target.find("#vocab_search").autocomplete({
        fixture:"/static/fixtures/search_results.json",
        start: function() {
            $input.removeClass("searchIdle").addClass("searchAjax");
        },
        success: function(query, resp) {
            $input.removeClass("searchAjax").addClass("searchIdle");
            $receiver.empty();
            $.each(resp, function(index, value){
                if (value.id === -1) {
                      $receiver.append("
No matches.
");
                      return;
                }
                var $li=$($.jqote(searchResultsTemplate,value));
                $li.data("node",value);
                $li.find(".path_node").hover(function(){$(this).addClass("over");},
                                             function(){$(this).removeClass("over");});
                $li.find(".path_node").each(function(index,element){

                   $(element).click(function(evt){
                       reloadBrowser("#" + value.path[parseInt($(evt.target).attr("pathid"))].id);
                       $("#showBrowse").trigger("click");
                       return false;
                   });

                });

                if (value.child_ref){
                     if ($.inArray(value.id, selected.folders)!=-1){
                         $li.addClass("added");
                     }
                }else{
                      if ($.inArray(value.id, selected.leaves)!=-1){
                        $li.addClass("added");
                      }
                }

                $li.filter(".folder").hover(function(){
                   $(this).addClass("list_on");
                }, function(){
                   $(this).removeClass("list_on");
                });
                $li.bind("addItemEvent",function(){
                    addNode($(this).data("node"));
                    $(this).addClass("added");
                    return false;
                });
                $li.hover(function(){
                     $(this).addClass("list_on");
                  }, function(){

                     $(this).removeClass("list_on");
                  });
                $li.click(function(){
                   var info = $(this).data("node");
                   if (info.child_ref){
                       reloadBrowser("#"+info.id);
                   }else if (info.path){
                       reloadBrowser("#"+info.path[info.path.length-1].id);
                   }else{
                       reloadBrowser("");
                   }
                $("#showBrowse").trigger("click");
                   return false;
                });

                $receiver.append($li);
            });

            $receiver.find(".button-add").click(function(){
                $(this).trigger("addItemEvent");
                $(this).attr("disabled", "disabled");
                return false;
            });
        },
        error: function(){
            $input.removeClass("searchAjax").addClass("searchIdle");
        }
    }, 'Search criteria...').helptext('Search criteria...');

    $target.find("#add-to-query").click(function(){
          var tree =  [{
                        'type': 'logic',
                        'operator': 'or',
                        'children': [{
                            'type': 'field',
                            'id': 1,
                            'operator': 'in',
                            'value': selected.leaves
                        }, {
                            'type': 'field',
                            'id': 2,
                            'operator': 'in',
                            'value': selected.folders
                        }]
                      }];
           $target.trigger("queryEvent", tree);
           console.log(tree);
       });
    $("body").trigger("widgetLoadedEvent", $target);
})();<|endoftext|>