<commit_before>import delegate from 'dom-delegate'
import throttle from 'lodash.throttle'
import { bind } from './adapter/dom/events'
import {
  CLASS_BUTTON,
  CLASS_HOVERED
} from './adapter/constants'

function handleWith (fn) {
  return event => {
    if (fn(event.target || event.srcElement)) {
      event.preventDefault()
    }
  }
}

function handleEscapeWith (fn) {
  return event => event.keyCode === 27 && fn()
}

export function bindEvents ({
  toggleHandler,
  dismiss,
  layoutPopovers,
  resizePopovers,
  hoverHandler,
  unhoverHandler
}) {
  const scrollHandler = throttle(layoutPopovers)
  const resizeHandler = throttle(() => {
    layoutPopovers()
    resizePopovers()
  })

  bind(document, 'touchend', handleWith(toggleHandler))
  bind(document, 'click', handleWith(toggleHandler))
  bind(document, 'keyup', handleEscapeWith(dismiss))
  bind(document, 'gestureend', scrollHandler)
  bind(window, 'scroll', scrollHandler)
  bind(window, 'resize', resizeHandler)

  delegate(document).on('mouseover', `.${CLASS_BUTTON}`, handleWith(hoverHandler))
  delegate(document).on('mouseout', `.${CLASS_HOVERED}`, handleWith(unhoverHandler))
}
<commit_msg>Layout was being called twice.<commit_after>import delegate from 'dom-delegate'
import throttle from 'lodash.throttle'
import { bind } from './adapter/dom/events'
import {
  CLASS_BUTTON,
  CLASS_HOVERED
} from './adapter/constants'

function handleWith (fn) {
  return event => {
    if (fn(event.target || event.srcElement)) {
      event.preventDefault()
    }
  }
}

function handleEscapeWith (fn) {
  return event => event.keyCode === 27 && fn()
}

export function bindEvents ({
  toggleHandler,
  dismiss,
  layoutPopovers,
  resizePopovers,
  hoverHandler,
  unhoverHandler
}) {
  bind(document, 'touchend', handleWith(toggleHandler))
  bind(document, 'click', handleWith(toggleHandler))
  bind(document, 'keyup', handleEscapeWith(dismiss))
  bind(document, 'gestureend', throttle(layoutPopovers))
  bind(window, 'scroll', throttle(layoutPopovers))
  bind(window, 'resize', throttle(resizePopovers))

  delegate(document).on('mouseover', `.${CLASS_BUTTON}`, handleWith(hoverHandler))
  delegate(document).on('mouseout', `.${CLASS_HOVERED}`, handleWith(unhoverHandler))
}
<|endoftext|>


<commit_before>$(document).ready(function(){
  module('String.score');

  test('Exact match', function(){
    expect(1);
    equals('Hello World'.score('Hello World'), 1.0, 'Exact matches should score 1.0');
  });

  test('Not matchhing', function(){
    expect(2);
    equals("hello world".score("hellx"), 0, 'non-existint charactor in match should return 0');
    equals("hello world".score("hello_world"),0, 'non-existint charactor in match should return 0');
  });

  test('Match must be sequential', function(){
    equals('Hello World'.score('WH'), 0, 'Matches out of order should return 0');
  });

  test('Same case should match better then wrong case', function(){
    ok('Hello World'.score('hello')<'Hello World'.score('Hello'));
  });

  test('Higher score for closer matches', function(){
    ok('Hello World'.score('H')<'Hello World'.score('He'), '"He" should match "Hello World" better then "H" does');
  });

  test('Matching with wrong case', function(){
    ok("Hillsdale Michigan".score("himi")>0, 'should match first matchable letter regardless of case');
  });

  module('Advanced Scoreing Methods');
  test('consecutive letter bonus', function(){
    expect(1);
    ok('Hello World'.score('Hel') > 'Hello World'.score('Hld'), '"Hel" should match "Hello World" better then "Hld"');
  });

  test('Acronym bonus', function(){
    expect(6);
    ok('Hello World'.score('HW') > 'Hello World'.score('Ho'), '"HW" should score higher with "Hello World" then Ho');
    ok('yet another Hello World'.score('yaHW') > 'Hello World'.score('yet another'));
    ok("Hillsdale Michigan".score("HiMi") > "Hillsdale Michigan".score("Hil"), '"HiMi" should match "Hillsdale Michigan" higher then "Hil"');
    ok("Hillsdale Michigan".score("HiMi") > "Hillsdale Michigan".score("illsda"));
    ok("Hillsdale Michigan".score("HiMi") > "Hillsdale Michigan".score("hills"));
    ok("Hillsdale Michigan".score("HiMi") < "Hillsdale Michigan".score("hillsd"));
  });

  test('Beginning of string bonus', function(){
    expect(2);
    ok("Hillsdale".score("hi") > "Chippewa".score("hi"));
    ok("hello world".score("h") > "hello world".score("w"), 'should have a bonus for matching first letter');
  });

  test('proper string weights', function(){
    ok("Research Resources North".score('res') > "Mary Conces".score('res'), 'res matches "Mary Conces" better then "Research Resources North"');

    ok("Research Resources North".score('res') > "Bonnie Strathern - Southwest Michigan Title Search".score('res'));
  });

  test('Start of String bonus', function(){
    ok("Mary Large".score('mar') > "Large Mary".score('mar'));
    ok("Silly Mary Large".score('mar') === "Silly Large Mary".score('mar')); // ensure start of string bonus only on start of string
  });

  module('Fuzzy String');
  test('should pass with mismatch when fuzzy', function(){
    expect(4);
    equal('Hello World'.score('Hz'), 0, 'should score 0 without a specified fuzzyness.');
    ok('Hello World'.score('Hz', 0.5) < 'Hello World'.score('H', 0.5), 'fuzzy matches should be worse then good ones');
    ok('Hello World'.score('Hz', 0.9) < 'Hello World'.score('H', 0.5), 'higher fuzzyness should yield higher scores');
    ok("hello world".score("hello worl", 0.5) > "hello world".score("hello wor1", 0.5), 'mismatch should always be worse');
  });

  module('Benchmark');
      test('Expand to see time to score', function(){
        var iterations = 4000;

        var start1 = new Date().valueOf();
        for(i=iterations;i>0;i--){ "hello world".score("h"); }
        var end1 = new Date().valueOf();
        var t1=end1-start1;
        ok(true, t1 + ' miliseconds to do '+iterations+' iterations of "hello world".score("h")');

        var start2 = new Date().valueOf();
        for(i=iterations;i>0;i--){ "hello world".score("hw"); }
        var end2 = new Date().valueOf();
        var t2=end2-start2;
        ok(true, t2 + ' miliseconds to do '+iterations+' iterations of "hello world".score("hw")');

        var start3 = new Date().valueOf();
        for(i=iterations;i>0;i--){ "hello world".score("hello world"); }
        var end3 = new Date().valueOf();
        var t3=end3-start3;
        ok(true, t3 + ' miliseconds to do '+iterations+' iterations of "hello world".score("hello world")');

        var start4 = new Date().valueOf();
        for(i=iterations;i>0;i--){ "hello any world that will listen".score("hlo wrdthlstn"); }
        var end4 = new Date().valueOf();
        var t4=end4-start4;
        ok(true, t4 + ' miliseconds to do '+iterations+' iterations of "hello any world that will listen".score("hlo wrdthlstn")');

        var start5 = new Date().valueOf();
        for(i=iterations;i>0;i--){ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.".score("Lorem i dor coecadipg et, Duis aute irure dole nulla. qui ofa mot am l"); }
        var end5 = new Date().valueOf();
        var t5=end5-start5;
        ok(true, t5 + ' miliseconds to do '+iterations+' iterations of 446 character string scoring a 70 character match');

        ok(true, 'score (smaller is faster): '+ (t1+t2+t3+t4+t5)/5);
      });
});<commit_msg>Update tests for better coverage<commit_after>$(document).ready(function(){
  module('String.score');

    test('Exact match', function(){
      expect(1);
      equals('Hello World'.score('Hello World'), 1.0, 'Exact matches should score 1.0');
    });

    test('Not matchhing', function(){
      expect(2);
      equals("hello world".score("hellx"), 0, 'non-existint charactor in match should return 0');
      equals("hello world".score("hello_world"),0, 'non-existint charactor in match should return 0');
    });

    test('Match must be sequential', function(){
      equals('Hello World'.score('WH'), 0, 'Matches out of order should return 0');
    });

    test('Same case should match better then wrong case', function(){
      ok('Hello World'.score('hello')<'Hello World'.score('Hello'));
    });

    test('Higher score for closer matches', function(){
      ok('Hello World'.score('H')<'Hello World'.score('He'), '"He" should match "Hello World" better then "H" does');
    });

    test('Matching with wrong case', function(){
      ok("Hillsdale Michigan".score("himi")>0, 'should match first matchable letter regardless of case');
    });

    test('should have proper relative weighting', function(){
      ok( "hello world".score("e")          < "hello world".score("h") );
      ok( "hello world".score("h")          < "hello world".score("he") );
      ok( "hello world".score("hel")        < "hello world".score("hell") );
      ok( "hello world".score("hell")       < "hello world".score("hello") );
      ok( "hello world".score("hello")      < "hello world".score("helloworld") );
      ok( "hello world".score("helloworl")  < "hello world".score("hello worl") );
      ok( "hello world".score("hello worl") < "hello world".score("hello world") );
    });

  module('Advanced Scoreing Methods');
    test('consecutive letter bonus', function(){
      expect(1);
      ok('Hello World'.score('Hel') > 'Hello World'.score('Hld'), '"Hel" should match "Hello World" better then "Hld"');
    });

    test('Acronym bonus', function(){
      expect(6);
      ok('Hello World'.score('HW') > 'Hello World'.score('Ho'), '"HW" should score higher with "Hello World" then Ho');
      ok('yet another Hello World'.score('yaHW') > 'Hello World'.score('yet another'));
      ok("Hillsdale Michigan".score("HiMi") > "Hillsdale Michigan".score("Hil"), '"HiMi" should match "Hillsdale Michigan" higher then "Hil"');
      ok("Hillsdale Michigan".score("HiMi") > "Hillsdale Michigan".score("illsda"));
      ok("Hillsdale Michigan".score("HiMi") > "Hillsdale Michigan".score("hills"));
      ok("Hillsdale Michigan".score("HiMi") < "Hillsdale Michigan".score("hillsd"));
    });

    test('Beginning of string bonus', function(){
      expect(2);
      ok("Hillsdale".score("hi") > "Chippewa".score("hi"));
      ok("hello world".score("h") > "hello world".score("w"), 'should have a bonus for matching first letter');
    });

    test('proper string weights', function(){
      ok("Research Resources North".score('res') > "Mary Conces".score('res'), 'res matches "Mary Conces" better then "Research Resources North"');

      ok("Research Resources North".score('res') > "Bonnie Strathern - Southwest Michigan Title Search".score('res'));
    });

    test('Start of String bonus', function(){
      ok("Mary Large".score('mar') > "Large Mary".score('mar'));
      ok("Silly Mary Large".score('mar') === "Silly Large Mary".score('mar')); // ensure start of string bonus only on start of string
    });

  module('Fuzzy String');
    test('should should score', function(){
      expect(3);
      equal('Hello World'.score('Hz'), 0, 'should score 0 without a specified fuzzyness.');
      ok('Hello World'.score('Hz', 0.5) < 'Hello World'.score('H', 0.5), 'fuzzy matches should be worse then good ones');
      ok("hello world".score("hello worl", 0.5) > "hello world".score("hello wor1", 0.5), 'mismatch should always be worse');
    });

    test('should have varying degrees of fuzzyness', function(){
      expect(1);
      ok('Hello World'.score('Hz', 0.9) > 'Hello World'.score('Hz', 0.5), 'higher fuzzyness should yield higher scores');
    });

  module('Benchmark');
    test('Expand to see time to score', function(){
      var iterations = 4000;

      var start1 = new Date().valueOf();
      for(i=iterations;i>0;i--){ "hello world".score("h"); }
      var end1 = new Date().valueOf();
      var t1=end1-start1;
      ok(true, t1 + ' miliseconds to do '+iterations+' iterations of "hello world".score("h")');

      var start2 = new Date().valueOf();
      for(i=iterations;i>0;i--){ "hello world".score("hw"); }
      var end2 = new Date().valueOf();
      var t2=end2-start2;
      ok(true, t2 + ' miliseconds to do '+iterations+' iterations of "hello world".score("hw")');

      var start3 = new Date().valueOf();
      for(i=iterations;i>0;i--){ "hello world".score("hello world"); }
      var end3 = new Date().valueOf();
      var t3=end3-start3;
      ok(true, t3 + ' miliseconds to do '+iterations+' iterations of "hello world".score("hello world")');

      var start4 = new Date().valueOf();
      for(i=iterations;i>0;i--){ "hello any world that will listen".score("hlo wrdthlstn"); }
      var end4 = new Date().valueOf();
      var t4=end4-start4;
      ok(true, t4 + ' miliseconds to do '+iterations+' iterations of "hello any world that will listen".score("hlo wrdthlstn")');

      var start5 = new Date().valueOf();
      for(i=iterations;i>0;i--){ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.".score("Lorem i dor coecadipg et, Duis aute irure dole nulla. qui ofa mot am l"); }
      var end5 = new Date().valueOf();
      var t5=end5-start5;
      ok(true, t5 + ' miliseconds to do '+iterations+' iterations of 446 character string scoring a 70 character match');

      ok(true, 'score (smaller is faster): '+ (t1+t2+t3+t4+t5)/5);
    });
});<|endoftext|>


<commit_before>/*!
* Modal for the Styleguide Layer
* For both annotations and code/info
*
* Copyright (c) 2016 Dave Olsen, http://dmolsen.com
* Licensed under the MIT license
*
* @requires panels-util.js
* @requires url-handler.js
*
*/

var modalStyleguide = {

  // set up some defaults
  active:       [ ],
  targetOrigin: (window.location.protocol === 'file:') ? '*' : window.location.protocol+'//'+window.location.host,

  /**
  * initialize the modal window
  */
  onReady: function() {

    // go through the panel toggles and add click event
    var els = document.querySelectorAll('.sg-pattern-extra-toggle');
    for (var i = 0; i < els.length; ++i) {
      els[i].onclick = (function(e) {
          e.preventDefault();
          var patternPartial = this.getAttribute('data-patternpartial');
          modalStyleguide.toggle(patternPartial);
      });
    }

  },

  /**
  * toggle the modal window open and closed
  */
  toggle: function(patternPartial) {
    if ((modalStyleguide.active[patternPartial] === undefined) || !modalStyleguide.active[patternPartial]) {
      var el = document.getElementById('sg-pattern-data-'+patternPartial);
      modalStyleguide.collectAndSend(el, true, false);
    } else {
      modalStyleguide.close(patternPartial);
    }

  },

  /**
  * open the modal window
  */
  open: function(patternPartial, content) {

    // make sure templateRendered is modified to be an HTML element
    var div       = document.createElement('div');
    div.innerHTML = content;
    content       = document.createElement('div').appendChild(div).querySelector('div');

    // add click events
    content = panelsUtil.addClickEvents(content, patternPartial);

    // make sure the modal viewer and other options are off just in case
    modalStyleguide.close(patternPartial);

    // note it's turned on in the viewer
    modalStyleguide.active[patternPartial] = true;

    // make sure there's no content
    div = document.getElementById('sg-pattern-extra-'+patternPartial);
    if (div.childNodes.length > 0) {
      div.removeChild(div.childNodes[0]);
    }

    // add the content
    document.getElementById('sg-pattern-extra-'+patternPartial).appendChild(content);

    // show the modal
    document.getElementById('sg-pattern-extra-toggle-'+patternPartial).classList.add('active');
    document.getElementById('sg-pattern-extra-'+patternPartial).classList.add('active');

  },

  /**
  * close the modal window
  */
  close: function(patternPartial) {

    // not that the modal viewer is no longer active
    modalStyleguide.active[patternPartial] = false;

    // hide the modal, look at info-panel.js
    document.getElementById('sg-pattern-extra-toggle-'+patternPartial).classList.remove('active');
    document.getElementById('sg-pattern-extra-'+patternPartial).classList.remove('active');

  },

  collectAndSend: function(el, iframePassback, switchText) {
    var patternData = JSON.parse(el.innerHTML);
    patternMarkupEl = document.querySelector('#'+patternData.patternPartial+' > .sg-pattern-example');
    patternData.patternMarkup = (patternMarkupEl !== null) ? patternMarkupEl.innerHTML : document.querySelector('body').innerHTML;
    modalStyleguide.patternQueryInfo(patternData, iframePassback, switchText);
  },

  /**
  * return the pattern info to the top level
  */
  patternQueryInfo: function(patternData, iframePassback, switchText) {

    // send a message to the pattern
    try {
      var obj = JSON.stringify({ 'event': 'patternLab.patternQueryInfo', 'patternData': patternData, 'iframePassback': iframePassback, 'switchText': switchText});
      parent.postMessage(obj, modalStyleguide.targetOrigin);
    } catch(e) {}

  },

  /**
  * toggle the comment pop-up based on a user clicking on the pattern
  * based on the great MDN docs at https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
  * @param  {Object}      event info
  */
  receiveIframeMessage: function(event) {

    var i;

    // does the origin sending the message match the current host? if not dev/null the request
    if ((window.location.protocol !== 'file:') && (event.origin !== window.location.protocol+'//'+window.location.host)) {
      return;
    }

    var data = {};
    try {
      data = (typeof event.data !== 'string') ? event.data : JSON.parse(event.data);
    } catch(e) {}

    // see if it got a path to replace
    if ((data.event !== undefined) && (data.event == 'patternLab.patternQuery')) {

      var els, iframePassback, patternData, patternMarkupEl;

      // find all elements related to pattern info
      els = document.querySelectorAll('.sg-pattern-data');
      iframePassback = (els.length > 1);

      // send each up to the parent to be read and compiled into panels
      for (i = 0; i < els.length; i++) {
        modalStyleguide.collectAndSend(els[i], iframePassback, data.switchText);
      }

    } else if ((data.event !== undefined) && (data.event == 'patternLab.patternModalInsert')) {

      // insert the previously rendered content being passed from the iframe
      modalStyleguide.open(data.patternPartial, data.modalContent);

    } else if ((data.event !== undefined) && (data.event == 'patternLab.annotationsHighlightShow')) {

      var elsToHighlight, j, item, span;

      // go over the supplied annotations
      for (i = 0; i < data.annotations.length; i++) {

        item = data.annotations[i];
        elsToHighlight = document.querySelectorAll(item.el);

        if (elsToHighlight.length > 0) {

          for (j = 0; j < elsToHighlight.length; j++) {

            elsToHighlight[j].classList.add('has-annotation');

            span = document.createElement('span');
            span.innerHTML = item.displayNumber;
            span.classList.add('annotation-tip');

            if (window.getComputedStyle(elsToHighlight[j],null).getPropertyValue('max-height') == '0px') {
              span.style.display = 'none';
            }

            annotationTip = document.querySelector(item.el+' > span.annotation-tip');
            if (annotationTip === null) {
              elsToHighlight[j].insertBefore(span,elsToHighlight[j].firstChild);
            } else {
              annotationTip.style.display = 'inline';
            }

            elsToHighlight[j].onclick = (function(item) {
              return function(e) {
                e.preventDefault();
                e.stopPropagation();
                var obj = JSON.stringify({'event': 'patternLab.annotationNumberClicked', 'displayNumber': item.displayNumber });
                parent.postMessage(obj, modalStyleguide.targetOrigin);
              };
            })(item);

          }

        }

      }

    } else if ((data.event !== undefined) && (data.event == 'patternLab.annotationsHighlightHide')) {

      elsToHide = document.querySelectorAll('.has-annotation');
      for (i = 0; i < elsToHide.length; i++) {
        elsToHide[i].classList.remove('has-annotation');
      }
      elsToHide = document.querySelectorAll('.annotation-tip');
      for (i = 0; i < elsToHide.length; i++) {
        elsToHide[i].style.display = 'none';
      }

    } else if ((data.event !== undefined) && (data.event == 'patternLab.patternModalClose')) {

      var keys = [];
      for (var k in modalStyleguide.active) {
        keys.push(k);
      }
      for (i = 0; i < keys.length; i++) {
        var patternPartial = keys[i];
        if (modalStyleguide.active[patternPartial]) {
          modalStyleguide.close(patternPartial);
        }
      }

    }

  }

};

// when the document is ready make sure the modal is ready
modalStyleguide.onReady();
window.addEventListener('message', modalStyleguide.receiveIframeMessage, false);
<commit_msg>adding better comments<commit_after>/*!
* Modal for the Styleguide Layer
* For both annotations and code/info
*
* Copyright (c) 2016 Dave Olsen, http://dmolsen.com
* Licensed under the MIT license
*
* @requires panels-util.js
* @requires url-handler.js
*
*/

var modalStyleguide = {

  // set up some defaults
  active:       [ ],
  targetOrigin: (window.location.protocol === 'file:') ? '*' : window.location.protocol+'//'+window.location.host,

  /**
  * initialize the modal window
  */
  onReady: function() {

    // go through the panel toggles and add click event
    var els = document.querySelectorAll('.sg-pattern-extra-toggle');
    for (var i = 0; i < els.length; ++i) {
      els[i].onclick = (function(e) {
          e.preventDefault();
          var patternPartial = this.getAttribute('data-patternpartial');
          modalStyleguide.toggle(patternPartial);
      });
    }

  },

  /**
  * toggle the modal window open and closed based on clicking the pip
  * @param  {String}       the patternPartial that identifies what needs to be toggled
  */
  toggle: function(patternPartial) {
    if ((modalStyleguide.active[patternPartial] === undefined) || !modalStyleguide.active[patternPartial]) {
      var el = document.getElementById('sg-pattern-data-'+patternPartial);
      modalStyleguide.collectAndSend(el, true, false);
    } else {
      modalStyleguide.close(patternPartial);
    }

  },

  /**
  * open the modal window for a view-all entry
  * @param  {String}       the patternPartial that identifies what needs to be opened
  * @param  {String}       the content that should be inserted
  */
  open: function(patternPartial, content) {

    // make sure templateRendered is modified to be an HTML element
    var div       = document.createElement('div');
    div.innerHTML = content;
    content       = document.createElement('div').appendChild(div).querySelector('div');

    // add click events
    content = panelsUtil.addClickEvents(content, patternPartial);

    // make sure the modal viewer and other options are off just in case
    modalStyleguide.close(patternPartial);

    // note it's turned on in the viewer
    modalStyleguide.active[patternPartial] = true;

    // make sure there's no content
    div = document.getElementById('sg-pattern-extra-'+patternPartial);
    if (div.childNodes.length > 0) {
      div.removeChild(div.childNodes[0]);
    }

    // add the content
    document.getElementById('sg-pattern-extra-'+patternPartial).appendChild(content);

    // show the modal
    document.getElementById('sg-pattern-extra-toggle-'+patternPartial).classList.add('active');
    document.getElementById('sg-pattern-extra-'+patternPartial).classList.add('active');

  },

  /**
  * close the modal window for a view-all entry
  * @param  {String}       the patternPartial that identifies what needs to be closed
  */
  close: function(patternPartial) {

    // not that the modal viewer is no longer active
    modalStyleguide.active[patternPartial] = false;

    // hide the modal, look at info-panel.js
    document.getElementById('sg-pattern-extra-toggle-'+patternPartial).classList.remove('active');
    document.getElementById('sg-pattern-extra-'+patternPartial).classList.remove('active');

  },

  /**
  * get the data that needs to be send to the viewer for rendering
  * @param  {Element}      the identifier for the element that needs to be collected
  * @param  {Boolean}      if the refresh is of a view-all view and the content should be sent back
  * @param  {Boolean}      if the text in the dropdown should be switched
  */
  collectAndSend: function(el, iframePassback, switchText) {
    var patternData = JSON.parse(el.innerHTML);
    patternMarkupEl = document.querySelector('#'+patternData.patternPartial+' > .sg-pattern-example');
    patternData.patternMarkup = (patternMarkupEl !== null) ? patternMarkupEl.innerHTML : document.querySelector('body').innerHTML;
    modalStyleguide.patternQueryInfo(patternData, iframePassback, switchText);
  },

  /**
  * return the pattern info to the top level
  * @param  {Object}       the content that will be sent to the viewer for rendering
  * @param  {Boolean}      if the refresh is of a view-all view and the content should be sent back
  * @param  {Boolean}      if the text in the dropdown should be switched
  */
  patternQueryInfo: function(patternData, iframePassback, switchText) {

    // send a message to the pattern
    try {
      var obj = JSON.stringify({ 'event': 'patternLab.patternQueryInfo', 'patternData': patternData, 'iframePassback': iframePassback, 'switchText': switchText});
      parent.postMessage(obj, modalStyleguide.targetOrigin);
    } catch(e) {}

  },

  /**
  * toggle the comment pop-up based on a user clicking on the pattern
  * based on the great MDN docs at https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
  * @param  {Object}      event info
  */
  receiveIframeMessage: function(event) {

    var i;

    // does the origin sending the message match the current host? if not dev/null the request
    if ((window.location.protocol !== 'file:') && (event.origin !== window.location.protocol+'//'+window.location.host)) {
      return;
    }

    var data = {};
    try {
      data = (typeof event.data !== 'string') ? event.data : JSON.parse(event.data);
    } catch(e) {}

    // see if it got a path to replace
    if ((data.event !== undefined) && (data.event == 'patternLab.patternQuery')) {

      var els, iframePassback, patternData, patternMarkupEl;

      // find all elements related to pattern info
      els = document.querySelectorAll('.sg-pattern-data');
      iframePassback = (els.length > 1);

      // send each up to the parent to be read and compiled into panels
      for (i = 0; i < els.length; i++) {
        modalStyleguide.collectAndSend(els[i], iframePassback, data.switchText);
      }

    } else if ((data.event !== undefined) && (data.event == 'patternLab.patternModalInsert')) {

      // insert the previously rendered content being passed from the iframe
      modalStyleguide.open(data.patternPartial, data.modalContent);

    } else if ((data.event !== undefined) && (data.event == 'patternLab.annotationsHighlightShow')) {

      var elsToHighlight, j, item, span;

      // go over the supplied annotations
      for (i = 0; i < data.annotations.length; i++) {

        item = data.annotations[i];
        elsToHighlight = document.querySelectorAll(item.el);

        if (elsToHighlight.length > 0) {

          for (j = 0; j < elsToHighlight.length; j++) {

            elsToHighlight[j].classList.add('has-annotation');

            span = document.createElement('span');
            span.innerHTML = item.displayNumber;
            span.classList.add('annotation-tip');

            if (window.getComputedStyle(elsToHighlight[j],null).getPropertyValue('max-height') == '0px') {
              span.style.display = 'none';
            }

            annotationTip = document.querySelector(item.el+' > span.annotation-tip');
            if (annotationTip === null) {
              elsToHighlight[j].insertBefore(span,elsToHighlight[j].firstChild);
            } else {
              annotationTip.style.display = 'inline';
            }

            elsToHighlight[j].onclick = (function(item) {
              return function(e) {
                e.preventDefault();
                e.stopPropagation();
                var obj = JSON.stringify({'event': 'patternLab.annotationNumberClicked', 'displayNumber': item.displayNumber });
                parent.postMessage(obj, modalStyleguide.targetOrigin);
              };
            })(item);

          }

        }

      }

    } else if ((data.event !== undefined) && (data.event == 'patternLab.annotationsHighlightHide')) {

      elsToHide = document.querySelectorAll('.has-annotation');
      for (i = 0; i < elsToHide.length; i++) {
        elsToHide[i].classList.remove('has-annotation');
      }
      elsToHide = document.querySelectorAll('.annotation-tip');
      for (i = 0; i < elsToHide.length; i++) {
        elsToHide[i].style.display = 'none';
      }

    } else if ((data.event !== undefined) && (data.event == 'patternLab.patternModalClose')) {

      var keys = [];
      for (var k in modalStyleguide.active) {
        keys.push(k);
      }
      for (i = 0; i < keys.length; i++) {
        var patternPartial = keys[i];
        if (modalStyleguide.active[patternPartial]) {
          modalStyleguide.close(patternPartial);
        }
      }

    }

  }

};

// when the document is ready make sure the modal is ready
modalStyleguide.onReady();
window.addEventListener('message', modalStyleguide.receiveIframeMessage, false);
<|endoftext|>


<commit_before>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %>
'use strict';

var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    minimist = require('minimist');

var paths = {
  styles: 'app/styles/**/*.scss',
  scripts: 'app/scripts/**/*.js',
  images: 'app/images/**/*.{gif,jpg,png,svg,webp}',
  extras: 'app/*.*',
  html: ['app/**/*.html'],
  index: 'app/**/_layout.html',
  clean: ['.tmp/*', 'public/**/*',
      '!public/assets', '!public/assets/**/*',
      '!public/index.php', '!public/.htaccess']
};

var knownOptions = {
  string: 'env',
  default: { env: process.env.NODE_ENV || 'staging' }
};

var options = minimist(process.argv.slice(2), knownOptions);

/**
 * gulp deploy-init
 */
gulp.task('deploy-init', function() {
  var server = options.env === 'production'
    ? '<%= remoteProduction %>'
    : '<%= remoteStaging %>';

  var branch = options.env === 'production'
    ? 'dokku-production'
    : 'dokku-staging';

  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      'git remote add ' + branch + ' dokku@' + server + ':' + slug,
      'git push ' + branch + ' master',
      'ssh dokku@' + server + ' mariadb:create ' + slug,
      'ssh dokku@' + server + ' mariadb:link ' + slug + ' ' + slug + ''
    ]));
});

/**
 * gulp deploy
 */
gulp.task('deploy', function() {
  var branch = options.env === 'production'
    ? 'dokku-production'
    : 'dokku-staging';

  return gulp.src('')
    .pipe($.shell([
      'git push ' + branch + ' master'
    ]));
});

/**
 * gulp db-dump-local
 */
gulp.task('db-dump-local', ['build'], function() {
  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      '[ -d ".tmp" ] || mkdir .tmp',
      'vagrant ssh --command "mysqldump -uroot -proot ' + slug + ' > /vagrant/.tmp/local.sql"'
    ]));
});

/**
 * gulp db-dump-remote
 */
gulp.task('db-dump-remote', ['build'], function() {
  var server = options.env === 'production'
    ? '<%= remoteProduction %>'
    : '<%= remoteStaging %>';

  var file = options.env === 'production'
    ? 'remote--production.sql'
    : 'remote--staging.sql';

  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      '[ -d ".tmp" ] || mkdir .tmp',
      'ssh dokku@' + server + ' mariadb:dumpraw ' + slug + ' | tee .tmp/' + file + ' > /dev/null'
    ]));
});

/**
 * gulp db-push
 */
gulp.task('db-push', ['db-dump-local'], function() {
  var server = options.env === 'production'
    ? '<%= remoteProduction %>'
    : '<%= remoteStaging %>';

  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      'ssh dokku@' + server + ' mariadb:console ' + slug + ' < .tmp/local.sql'
    ]));
});

/**
 * gulp db-pull
 */
gulp.task('db-pull', ['db-dump-remote'], function(){
  var file = options.env === 'production'
    ? 'remote--production.sql'
    : 'remote--staging.sql';

  var slug = '<%= _.slugify(slug) %>';

   return gulp.src('')
    .pipe($.shell([
      'vagrant ssh --command "mysql -uroot -proot ' + slug + ' < /vagrant/.tmp/ ' + file + '"'
    ]));
});

/**
 * gulp db-dump
 */
gulp.task('db-dump', [
    'clean',
    'db-dump-local',
    'db-dump-remote'
  ], function() {
    var file = options.env === 'production'
      ? 'remote--production.sql'
      : 'remote--staging.sql';

    return gulp.src([
        '.tmp/local.sql',
        '.tmp/ ' + file
      ])
      .pipe(gulp.dest('databases'));
});

/**
 * gulp styles
 */
gulp.task('styles', function() {
  return gulp.src([paths.styles])
    .pipe($.plumber())
    .pipe($.rubySass({
      style: 'expanded',
      precision: 10
    }))
    .pipe(gulp.dest('public/styles'))
});

/**
 * gulp scripts
 */
gulp.task('scripts', function() {
  return gulp.src(paths.scripts)
    .pipe($.changed('public/scripts'))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe(gulp.dest('public/scripts'));
});

/**
 * gulp images
 */
gulp.task('images', function () {
  return gulp.src(paths.images)
    .pipe($.changed('public/images'))
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('public/images'));
});

/**
 * gulp extras
 */
gulp.task('extras', function() {
  return gulp.src(paths.extras, { dot: true })
    .pipe($.changed('public'))
    .pipe(gulp.dest('public'));
});

/**
 * gulp clean
 */
gulp.task('clean', function(cb) {
  require('del')(paths.clean, cb);
});

/**
 * gulp html
 */
gulp.task('html', function() {
  return gulp.src(paths.html)
    .pipe($.changed('public'))
    .pipe(gulp.dest('public'));
})

/**
 * gulp build
 */
gulp.task('build', ['clean'], function() {
  gulp.start('build-useref');
});

/**
 * gulp build-useref
 */
gulp.task('build-useref', [
    'html',
    'images',
    'scripts',
    'styles',
    'extras'
  ], function() {
  var assets = $.useref.assets({searchPath: '{public,app}'});

  return gulp.src(paths.index)
    .pipe($.if(options.env !== 'production',
      $.multinject(['http://localhost:35729/livereload.js?snipver=1'], 'livereload')
    ))
    .pipe(assets)
    .pipe($.if(options.env === 'production', $.if('*.js', $.uglify())))
    .pipe($.if(options.env === 'production', $.if('*.css', $.csso())))
    .pipe($.if(options.env === 'production', $.if('*.css', $.autoprefixer('last 1 version'))))
    .pipe(assets.restore())
    .pipe($.useref())
    .pipe(gulp.dest('public'));
});

/**
 * gulp watch
 */
gulp.task('watch', function() {
  gulp.start('build-useref');

  $.livereload.listen();
  gulp.watch('public/**/*', $.livereload.changed);

  gulp.watch(paths.extras,  ['extras']);
  gulp.watch(paths.html,    ['html']);
  gulp.watch(paths.index,   ['build-useref']);
  gulp.watch(paths.scripts, ['scripts']);
  gulp.watch(paths.styles,  ['styles']);
  gulp.watch(paths.images,  ['images']);
});

/**
 * gulp
 */
gulp.task('default', ['build']);<commit_msg>sass load path<commit_after>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %>
'use strict';

var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    minimist = require('minimist');

var paths = {
  styles: 'app/styles/**/*.scss',
  scripts: 'app/scripts/**/*.js',
  images: 'app/images/**/*.{gif,jpg,png,svg,webp}',
  extras: 'app/*.*',
  html: ['app/**/*.html'],
  index: 'app/**/_layout.html',
  clean: ['.tmp/*', 'public/**/*',
      '!public/assets', '!public/assets/**/*',
      '!public/index.php', '!public/.htaccess']
};

var knownOptions = {
  string: 'env',
  default: { env: process.env.NODE_ENV || 'staging' }
};

var options = minimist(process.argv.slice(2), knownOptions);

/**
 * gulp deploy-init
 */
gulp.task('deploy-init', function() {
  var server = options.env === 'production'
    ? '<%= remoteProduction %>'
    : '<%= remoteStaging %>';

  var branch = options.env === 'production'
    ? 'dokku-production'
    : 'dokku-staging';

  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      'git remote add ' + branch + ' dokku@' + server + ':' + slug,
      'git push ' + branch + ' master',
      'ssh dokku@' + server + ' mariadb:create ' + slug,
      'ssh dokku@' + server + ' mariadb:link ' + slug + ' ' + slug + ''
    ]));
});

/**
 * gulp deploy
 */
gulp.task('deploy', function() {
  var branch = options.env === 'production'
    ? 'dokku-production'
    : 'dokku-staging';

  return gulp.src('')
    .pipe($.shell([
      'git push ' + branch + ' master'
    ]));
});

/**
 * gulp db-dump-local
 */
gulp.task('db-dump-local', ['build'], function() {
  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      '[ -d ".tmp" ] || mkdir .tmp',
      'vagrant ssh --command "mysqldump -uroot -proot ' + slug + ' > /vagrant/.tmp/local.sql"'
    ]));
});

/**
 * gulp db-dump-remote
 */
gulp.task('db-dump-remote', ['build'], function() {
  var server = options.env === 'production'
    ? '<%= remoteProduction %>'
    : '<%= remoteStaging %>';

  var file = options.env === 'production'
    ? 'remote--production.sql'
    : 'remote--staging.sql';

  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      '[ -d ".tmp" ] || mkdir .tmp',
      'ssh dokku@' + server + ' mariadb:dumpraw ' + slug + ' | tee .tmp/' + file + ' > /dev/null'
    ]));
});

/**
 * gulp db-push
 */
gulp.task('db-push', ['db-dump-local'], function() {
  var server = options.env === 'production'
    ? '<%= remoteProduction %>'
    : '<%= remoteStaging %>';

  var slug = '<%= _.slugify(slug) %>';

  return gulp.src('')
    .pipe($.shell([
      'ssh dokku@' + server + ' mariadb:console ' + slug + ' < .tmp/local.sql'
    ]));
});

/**
 * gulp db-pull
 */
gulp.task('db-pull', ['db-dump-remote'], function(){
  var file = options.env === 'production'
    ? 'remote--production.sql'
    : 'remote--staging.sql';

  var slug = '<%= _.slugify(slug) %>';

   return gulp.src('')
    .pipe($.shell([
      'vagrant ssh --command "mysql -uroot -proot ' + slug + ' < /vagrant/.tmp/ ' + file + '"'
    ]));
});

/**
 * gulp db-dump
 */
gulp.task('db-dump', [
    'clean',
    'db-dump-local',
    'db-dump-remote'
  ], function() {
    var file = options.env === 'production'
      ? 'remote--production.sql'
      : 'remote--staging.sql';

    return gulp.src([
        '.tmp/local.sql',
        '.tmp/ ' + file
      ])
      .pipe(gulp.dest('databases'));
});

/**
 * gulp styles
 */
gulp.task('styles', function() {
  return gulp.src([paths.styles])
    .pipe($.plumber())
    .pipe($.rubySass({
      loadPath: 'bower_components'
      style: 'expanded',
      precision: 10
    }))
    .pipe(gulp.dest('public/styles'))
});

/**
 * gulp scripts
 */
gulp.task('scripts', function() {
  return gulp.src(paths.scripts)
    .pipe($.changed('public/scripts'))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe(gulp.dest('public/scripts'));
});

/**
 * gulp images
 */
gulp.task('images', function () {
  return gulp.src(paths.images)
    .pipe($.changed('public/images'))
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('public/images'));
});

/**
 * gulp extras
 */
gulp.task('extras', function() {
  return gulp.src(paths.extras, { dot: true })
    .pipe($.changed('public'))
    .pipe(gulp.dest('public'));
});

/**
 * gulp clean
 */
gulp.task('clean', function(cb) {
  require('del')(paths.clean, cb);
});

/**
 * gulp html
 */
gulp.task('html', function() {
  return gulp.src(paths.html)
    .pipe($.changed('public'))
    .pipe(gulp.dest('public'));
})

/**
 * gulp build
 */
gulp.task('build', ['clean'], function() {
  gulp.start('build-useref');
});

/**
 * gulp build-useref
 */
gulp.task('build-useref', [
    'html',
    'images',
    'scripts',
    'styles',
    'extras'
  ], function() {
  var assets = $.useref.assets({searchPath: '{public,app}'});

  return gulp.src(paths.index)
    .pipe($.if(options.env !== 'production',
      $.multinject(['http://localhost:35729/livereload.js?snipver=1'], 'livereload')
    ))
    .pipe(assets)
    .pipe($.if(options.env === 'production', $.if('*.js', $.uglify())))
    .pipe($.if(options.env === 'production', $.if('*.css', $.csso())))
    .pipe($.if(options.env === 'production', $.if('*.css', $.autoprefixer('last 1 version'))))
    .pipe(assets.restore())
    .pipe($.useref())
    .pipe(gulp.dest('public'));
});

/**
 * gulp watch
 */
gulp.task('watch', function() {
  gulp.start('build-useref');

  $.livereload.listen();
  gulp.watch('public/**/*', $.livereload.changed);

  gulp.watch(paths.extras,  ['extras']);
  gulp.watch(paths.html,    ['html']);
  gulp.watch(paths.index,   ['build-useref']);
  gulp.watch(paths.scripts, ['scripts']);
  gulp.watch(paths.styles,  ['styles']);
  gulp.watch(paths.images,  ['images']);
});

/**
 * gulp
 */
gulp.task('default', ['build']);<|endoftext|>


<commit_before>(function() {

/*---------------------------------------------------
    Globals
---------------------------------------------------*/

var config = {};

/*---------------------------------------------------
    General
---------------------------------------------------*/

$().ready(function() {
    // Add events
    $('#login-form').submit(buildSubmit);
    $('a[target="_system"]').on('click', function(e) {
        e.preventDefault();
        window.open($(this).attr('href'), '_system');
    });

    // Issue #27
    // When input box is selected, the soft-keyboard is shown
    // but the input box focus is in the incorrect position.
    $('#address').on('touchstart', function() {
        $('#address').focus();
    });

    // On input selection, backup the current address.
    $('#address').on('focus', function() {
        $('#address').attr('currentValue', getAddressField());
    });

    // On input de-selection, restore backup if there is no content.
    $('#address').on('blur', function() {
        var $address = $('#address'),
            whitespaceRegex = /^\s*$/;

        if (whitespaceRegex.test(getAddressField())) {
            $address.val($address.attr('currentValue'));
        }
        $address.attr('currentValue', '');
    });

    // Work around CSS browser issues.
    supportBrowserQuirks();
});

$(document).on('deviceready', function() {
    // Add slight delay to allow DOM rendering to finish.
    // Avoids flicker on slower devices.
    setTimeout(function() {
        // allow the screen to dim when returning from the served app
        window.plugins.insomnia.allowSleepAgain();

        navigator.splashscreen.hide();
        $('.footer').removeClass('faded');

        // Load configuration
        window.phonegap.app.config.load(function(data) {
            // store the config data
            config = data;

            // load server address
            if (config.address) {
                $('#address').val(config.address);
            }

            setTimeout( function() {
                $('.alert').removeClass('alert');
                $('.visor').removeClass('pulse');
                $('.visor label').html('Hi!');
                $('.visor .eye').removeClass('faded');
            }, 1750);

            setTimeout( openBot, 2750);
            setTimeout( function() {
                $('.visor .eye').addClass('hidden');
            }, 3350 );
        });
    }, 350);
});

/*---------------------------------------------------
    UI - General
---------------------------------------------------*/

function openBot() {
    $('.monitor form').removeClass('hidden');
    setTimeout( function() {
        $('.panel.top').addClass('open');
        $('.visor').addClass('fade-out');
        $('.monitor form').removeClass('faded');
        setTimeout( function() {
            $('.visor').addClass('hidden');
        }, 550);
    }, 50);
}

function closeBot() {
    $('.visor').removeClass('hidden');
    setTimeout( function() {
        $('.panel.top').removeClass('open');
        $('.visor').removeClass('fade-out');
        $('.monitor form').addClass('faded');
        setTimeout( function() {
            $('.monitor form').addClass('hidden');
        }, 550);
    }, 50);
}

// Note that the bot needs to be closed to be able to view this
function updateMessage( msg ) {
    $('.visor').removeClass('pulse');
    $('.visor label').html( msg.toUpperCase() );
}

function errorMessage( msg ) {
    updateMessage( msg );
    $('.visor').removeClass('pulse');
    $('.monitor').addClass('alert');
}

function pulsingMessage( msg ) {
    updateMessage( msg );
    $('.visor').addClass('pulse');
}

/*---------------------------------------------------
    UI - Form
---------------------------------------------------*/

function buildSubmit() {
    closeBot();
    updateMessage('');
    setTimeout(function() {
        pulsingMessage( 'Connecting...' );
        onBuildSubmitSuccess();
    }, 500);

    return false;
}

function onBuildSubmitSuccess() {
    updateMessage( 'Downloading...' );

    // update config data
    config.URL = document.URL;
    config.address = getAddressField();

    window.phonegap.app.config.save(config, function() {
        // don't allow the screen to dim when serving an app
        window.plugins.insomnia.keepAwake();

        setTimeout( function() {
            window.phonegap.app.downloadZip({
                address: getAddress(),
                onProgress: function(data) {
                    if(data.status === 2) {
                        updateMessage('Extracting...');
                    }else if(data.status === 3) {
                        updateMessage('Success!');
                    }
                },
                onDownloadError: function(e) {
                    onBuildSubmitError('Upgrade CLI');
                    setTimeout(function() {
                        navigator.notification.alert(
                            'Hi! We\'ve recently improved the PhoneGap Developer App.\n\n' +
                            'Please update the PhoneGap CLI on your development machine to take advantage of the new features.',
                            function() {},
                            'Upgrade PhoneGap CLI'
                        );
                    }, 4000);
                }
            });
        }, 1000 );
    });
}

function onBuildSubmitError(message) {
    errorMessage('Error!');
    setTimeout(function() {
        message = message || 'Timed out!';
        errorMessage(message);
    }, 1500);

    setTimeout(function() {
        $('.monitor').removeClass('alert');
        updateMessage('');
        openBot();
    }, 3500);
}

function getAddressField() {
    var $address = $('#address'),
        address = $address.val() || $address.attr('placeholder');

    return address;
}

function getAddress(path) {
    var address = getAddressField();

    // default to http:// when no protocol exists
    address = (address.match(/^(.*:\/\/)/)) ? address : 'http://' + address;

    // append an optional path
    if (path) {
        address += '/' + path;

        // replace double forward slashes with a single forward-slash
        // except after the protocol (://)
        address = address.replace(/([^:])\/\//g, '$1/');
    }

    return address;
}

/*---------------------------------------------------
    Browser - Quirks
---------------------------------------------------*/

function supportBrowserQuirks() {
    // Issue #51
    // Windows Phone 8 does not support border-image
    if (/IEMobile\/10/.test(window.navigator.userAgent)) {
        var element = document.createElement('style');
        element.setAttribute('type', 'text/css');
        element.innerHTML = [
            '#bot .monitor .cover {',
            '   background-image: url(img/frame.png);',
            '   background-size: 270px 220px;',
            '   background-repeat: no-repeat;',
            '   border: none;',
            '}'
        ].join('\n');
        document.body.appendChild(element);
    }
}

})();
<commit_msg>[#282] - updated download error alert<commit_after>(function() {

/*---------------------------------------------------
    Globals
---------------------------------------------------*/

var config = {};

/*---------------------------------------------------
    General
---------------------------------------------------*/

$().ready(function() {
    // Add events
    $('#login-form').submit(buildSubmit);
    $('a[target="_system"]').on('click', function(e) {
        e.preventDefault();
        window.open($(this).attr('href'), '_system');
    });

    // Issue #27
    // When input box is selected, the soft-keyboard is shown
    // but the input box focus is in the incorrect position.
    $('#address').on('touchstart', function() {
        $('#address').focus();
    });

    // On input selection, backup the current address.
    $('#address').on('focus', function() {
        $('#address').attr('currentValue', getAddressField());
    });

    // On input de-selection, restore backup if there is no content.
    $('#address').on('blur', function() {
        var $address = $('#address'),
            whitespaceRegex = /^\s*$/;

        if (whitespaceRegex.test(getAddressField())) {
            $address.val($address.attr('currentValue'));
        }
        $address.attr('currentValue', '');
    });

    // Work around CSS browser issues.
    supportBrowserQuirks();
});

$(document).on('deviceready', function() {
    // Add slight delay to allow DOM rendering to finish.
    // Avoids flicker on slower devices.
    setTimeout(function() {
        // allow the screen to dim when returning from the served app
        window.plugins.insomnia.allowSleepAgain();

        navigator.splashscreen.hide();
        $('.footer').removeClass('faded');

        // Load configuration
        window.phonegap.app.config.load(function(data) {
            // store the config data
            config = data;

            // load server address
            if (config.address) {
                $('#address').val(config.address);
            }

            setTimeout( function() {
                $('.alert').removeClass('alert');
                $('.visor').removeClass('pulse');
                $('.visor label').html('Hi!');
                $('.visor .eye').removeClass('faded');
            }, 1750);

            setTimeout( openBot, 2750);
            setTimeout( function() {
                $('.visor .eye').addClass('hidden');
            }, 3350 );
        });
    }, 350);
});

/*---------------------------------------------------
    UI - General
---------------------------------------------------*/

function openBot() {
    $('.monitor form').removeClass('hidden');
    setTimeout( function() {
        $('.panel.top').addClass('open');
        $('.visor').addClass('fade-out');
        $('.monitor form').removeClass('faded');
        setTimeout( function() {
            $('.visor').addClass('hidden');
        }, 550);
    }, 50);
}

function closeBot() {
    $('.visor').removeClass('hidden');
    setTimeout( function() {
        $('.panel.top').removeClass('open');
        $('.visor').removeClass('fade-out');
        $('.monitor form').addClass('faded');
        setTimeout( function() {
            $('.monitor form').addClass('hidden');
        }, 550);
    }, 50);
}

// Note that the bot needs to be closed to be able to view this
function updateMessage( msg ) {
    $('.visor').removeClass('pulse');
    $('.visor label').html( msg.toUpperCase() );
}

function errorMessage( msg ) {
    updateMessage( msg );
    $('.visor').removeClass('pulse');
    $('.monitor').addClass('alert');
}

function pulsingMessage( msg ) {
    updateMessage( msg );
    $('.visor').addClass('pulse');
}

/*---------------------------------------------------
    UI - Form
---------------------------------------------------*/

function buildSubmit() {
    closeBot();
    updateMessage('');
    setTimeout(function() {
        pulsingMessage( 'Connecting...' );
        onBuildSubmitSuccess();
    }, 500);

    return false;
}

function onBuildSubmitSuccess() {
    updateMessage( 'Downloading...' );

    // update config data
    config.URL = document.URL;
    config.address = getAddressField();

    window.phonegap.app.config.save(config, function() {
        // don't allow the screen to dim when serving an app
        window.plugins.insomnia.keepAwake();

        setTimeout( function() {
            window.phonegap.app.downloadZip({
                address: getAddress(),
                onProgress: function(data) {
                    if(data.status === 2) {
                        updateMessage('Extracting...');
                    }else if(data.status === 3) {
                        updateMessage('Success!');
                    }
                },
                onDownloadError: function(e) {
                    onBuildSubmitError('Upgrade CLI');
                    setTimeout(function() {
                        navigator.notification.alert(
                            'Unable to download archive from the server.\n\n' +
                            'Please check your network settings.',
                            function() {},
                            'Ok'
                        );
                    }, 4000);
                }
            });
        }, 1000 );
    });
}

function onBuildSubmitError(message) {
    errorMessage('Error!');
    setTimeout(function() {
        message = message || 'Timed out!';
        errorMessage(message);
    }, 1500);

    setTimeout(function() {
        $('.monitor').removeClass('alert');
        updateMessage('');
        openBot();
    }, 3500);
}

function getAddressField() {
    var $address = $('#address'),
        address = $address.val() || $address.attr('placeholder');

    return address;
}

function getAddress(path) {
    var address = getAddressField();

    // default to http:// when no protocol exists
    address = (address.match(/^(.*:\/\/)/)) ? address : 'http://' + address;

    // append an optional path
    if (path) {
        address += '/' + path;

        // replace double forward slashes with a single forward-slash
        // except after the protocol (://)
        address = address.replace(/([^:])\/\//g, '$1/');
    }

    return address;
}

/*---------------------------------------------------
    Browser - Quirks
---------------------------------------------------*/

function supportBrowserQuirks() {
    // Issue #51
    // Windows Phone 8 does not support border-image
    if (/IEMobile\/10/.test(window.navigator.userAgent)) {
        var element = document.createElement('style');
        element.setAttribute('type', 'text/css');
        element.innerHTML = [
            '#bot .monitor .cover {',
            '   background-image: url(img/frame.png);',
            '   background-size: 270px 220px;',
            '   background-repeat: no-repeat;',
            '   border: none;',
            '}'
        ].join('\n');
        document.body.appendChild(element);
    }
}

})();
<|endoftext|>


<commit_before>const CompilerSupplier = require("./compilerSupplier");
const Config = require("@truffle/config");
const semver = require("semver");
const Profiler = require("./profiler");
const fse = require("fs-extra");
const { run } = require("./run");
const OS = require("os");
const cloneDeep = require("lodash/clonedeep");

const getSemverExpression = source => {
  return source.match(/pragma solidity(.*);/)[1].trim();
};

const getSemverExpressions = sources => {
  return sources.map(source => getSemverExpression(source));
};

const validateSemverExpressions = semverExpressions => {
  const { validRange } = semver;
  for (const expression of semverExpressions) {
    if (semver.validRange(expression) === null) {
      const message = `Invalid semver expression (${expression}) found in` +
        `one of your contract's imports.`;
      throw new Error(message);
    }
  }
};

// takes an array of versions and an array of semver expressions
// returns a version of the compiler or undefined if none can be found
const findNewestSatisfyingVersion = ({ solcReleases, semverExpressions }) => {
  // releases are ordered from newest to oldest
  return solcReleases.find(version => {
    return semverExpressions.every(expression =>
      semver.satisfies(version, expression)
    );
  });
};

const throwCompilerVersionNotFound = ({ path, semverExpressions }) => {
  const message =
    `Could not find a single version of the Solidity compiler that ` +
    `satisfies the following semver expressions obtained from your source ` +
    `files' pragma statements: ${semverExpressions.join(" - ")}. ` +
    `${OS.EOL}Please check the pragma statements for ${path} and its imports.`;
  throw new Error(message);
};

const compileWithPragmaAnalysis = async ({ paths, options }) => {
  const supplierOptions = {
    events: options.events,
    solcConfig: options.compilers.solc
  };
  const compilerSupplier = new CompilerSupplier(supplierOptions);
  const { releases } = await compilerSupplier.getReleases();

  // collect sources by the version of the Solidity compiler that they require
  const versionsAndSources = {};
  for (const path of paths) {
    const source = (await options.resolver.resolve(path)).body;

    const parserVersion = findNewestSatisfyingVersion({
      solcReleases: releases,
      semverExpressions: [getSemverExpression(source)]
    });
    if (!parserVersion) {
      throwCompilerVersionNotFound({
        path,
        semverExpressions: [getSemverExpression(source)]
      });
    }

    // allSources is of the format { [filename]: string }
    const { allSources } = await Profiler.requiredSourcesForSingleFile(
      options.with({
        path,
        base_path: options.contracts_directory,
        resolver: options.resolver,
        compilers: {
          solc: {
            version: parserVersion
          }
        }
      })
    );

    // get an array of all the semver expressions in the sources
    const semverExpressions = await getSemverExpressions(
      Object.values(allSources)
    );

    // this really just validates the expressions from the contracts' imports
    // as it has already determined the parser version for each contract
    validateSemverExpressions(semverExpressions);

    const newestSatisfyingVersion = findNewestSatisfyingVersion({
      solcReleases: releases,
      semverExpressions
    });
    if (!newestSatisfyingVersion) {
      throwCompilerVersionNotFound({
        path,
        semverExpressions
      });
    }

    if (versionsAndSources[newestSatisfyingVersion]) {
      versionsAndSources[newestSatisfyingVersion] = {
        ...versionsAndSources[newestSatisfyingVersion],
        ...allSources
      };
    } else {
      versionsAndSources[newestSatisfyingVersion] = allSources;
    }
  }

  const compilations = [];
  for (const compilerVersion of Object.keys(versionsAndSources)) {
    const compilationOptions = Object.assign(
      {},
      { compilers: cloneDeep(options.compilers) }
    );
    compilationOptions.compilers.solc.version = compilerVersion;

    const config = Config.default().with(compilationOptions);
    const compilation = await run(
      versionsAndSources[compilerVersion],
      config
    );
    if (compilation.contracts.length > 0) {
      compilations.push(compilation);
    }
  }
  return { compilations };
};

module.exports = {
  compileWithPragmaAnalysis
};
<commit_msg>Correct require statement for lodash.clonedeep<commit_after>const CompilerSupplier = require("./compilerSupplier");
const Config = require("@truffle/config");
const semver = require("semver");
const Profiler = require("./profiler");
const fse = require("fs-extra");
const { run } = require("./run");
const OS = require("os");
const cloneDeep = require("lodash.clonedeep");

const getSemverExpression = source => {
  return source.match(/pragma solidity(.*);/)[1].trim();
};

const getSemverExpressions = sources => {
  return sources.map(source => getSemverExpression(source));
};

const validateSemverExpressions = semverExpressions => {
  const { validRange } = semver;
  for (const expression of semverExpressions) {
    if (semver.validRange(expression) === null) {
      const message = `Invalid semver expression (${expression}) found in` +
        `one of your contract's imports.`;
      throw new Error(message);
    }
  }
};

// takes an array of versions and an array of semver expressions
// returns a version of the compiler or undefined if none can be found
const findNewestSatisfyingVersion = ({ solcReleases, semverExpressions }) => {
  // releases are ordered from newest to oldest
  return solcReleases.find(version => {
    return semverExpressions.every(expression =>
      semver.satisfies(version, expression)
    );
  });
};

const throwCompilerVersionNotFound = ({ path, semverExpressions }) => {
  const message =
    `Could not find a single version of the Solidity compiler that ` +
    `satisfies the following semver expressions obtained from your source ` +
    `files' pragma statements: ${semverExpressions.join(" - ")}. ` +
    `${OS.EOL}Please check the pragma statements for ${path} and its imports.`;
  throw new Error(message);
};

const compileWithPragmaAnalysis = async ({ paths, options }) => {
  const supplierOptions = {
    events: options.events,
    solcConfig: options.compilers.solc
  };
  const compilerSupplier = new CompilerSupplier(supplierOptions);
  const { releases } = await compilerSupplier.getReleases();

  // collect sources by the version of the Solidity compiler that they require
  const versionsAndSources = {};
  for (const path of paths) {
    const source = (await options.resolver.resolve(path)).body;

    const parserVersion = findNewestSatisfyingVersion({
      solcReleases: releases,
      semverExpressions: [getSemverExpression(source)]
    });
    if (!parserVersion) {
      throwCompilerVersionNotFound({
        path,
        semverExpressions: [getSemverExpression(source)]
      });
    }

    // allSources is of the format { [filename]: string }
    const { allSources } = await Profiler.requiredSourcesForSingleFile(
      options.with({
        path,
        base_path: options.contracts_directory,
        resolver: options.resolver,
        compilers: {
          solc: {
            version: parserVersion
          }
        }
      })
    );

    // get an array of all the semver expressions in the sources
    const semverExpressions = await getSemverExpressions(
      Object.values(allSources)
    );

    // this really just validates the expressions from the contracts' imports
    // as it has already determined the parser version for each contract
    validateSemverExpressions(semverExpressions);

    const newestSatisfyingVersion = findNewestSatisfyingVersion({
      solcReleases: releases,
      semverExpressions
    });
    if (!newestSatisfyingVersion) {
      throwCompilerVersionNotFound({
        path,
        semverExpressions
      });
    }

    if (versionsAndSources[newestSatisfyingVersion]) {
      versionsAndSources[newestSatisfyingVersion] = {
        ...versionsAndSources[newestSatisfyingVersion],
        ...allSources
      };
    } else {
      versionsAndSources[newestSatisfyingVersion] = allSources;
    }
  }

  const compilations = [];
  for (const compilerVersion of Object.keys(versionsAndSources)) {
    const compilationOptions = Object.assign(
      {},
      { compilers: cloneDeep(options.compilers) }
    );
    compilationOptions.compilers.solc.version = compilerVersion;

    const config = Config.default().with(compilationOptions);
    const compilation = await run(
      versionsAndSources[compilerVersion],
      config
    );
    if (compilation.contracts.length > 0) {
      compilations.push(compilation);
    }
  }
  return { compilations };
};

module.exports = {
  compileWithPragmaAnalysis
};
<|endoftext|>


<commit_before>define([
  'summernote/core/list',
  'summernote/core/dom',
  'summernote/core/key',
  'summernote/core/agent'
], function (list, dom, key, agent) {
  var Clipboard = function (handler) {
    var $paste;

    this.attach = function (layoutInfo) {
      if (window.clipboardData || agent.isFF) {
        $paste = $('<div />').attr('contenteditable', true).css({
          position : 'absolute',
          left : -100000,
          opacity : 0
        });
        layoutInfo.editable().after($paste);
        $paste.on('paste', hPaste);

        layoutInfo.editable().on('keydown', function (e) {
          if (e.ctrlKey && e.keyCode === key.code.V) {
            handler.invoke('saveRange', layoutInfo.editable());
            $paste.focus();
          }
        });
      }

      layoutInfo.editable().on('paste', hPaste);
    };

    /**
     * paste clipboard image
     *
     * @param {Event} event
     */
    var hPaste = function (event) {
      var clipboardData = event.originalEvent.clipboardData;
      var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
      var $editable = layoutInfo.editable();

      if (clipboardData && clipboardData.items && clipboardData.items.length) {
        var item = list.head(clipboardData.items);
        if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
          handler.insertImages(layoutInfo, [item.getAsFile()]);
        }

        handler.invoke('editor.afterCommand', $editable);
      } else {
        // only can run if it has onImageUpload method
        if (!$editable.data('callbacks').onImageUpload || !$paste) {
          return;
        }

        setTimeout(function () {
          var node = $paste[0].firstChild;
          if (dom.isImg(node)) {
            handler.invoke('restoreRange', $editable);
            var dataURI = node.src;

            var decodedData = atob(dataURI.split(',')[1]);
            var array = new Uint8Array(decodedData.length);
            for (var i = 0; i < decodedData.length; i++) {
              array[i] = decodedData.charCodeAt(i);
            }

            var blob = new Blob([array], { type : 'image/png' });
            blob.name = 'clipboard.png';
            handler.invoke('focus', $editable);
            handler.insertImages(layoutInfo, [blob]);
            $paste.empty();
          } else {
            var pasteContent = $('<div />').html($paste.html());
            handler.invoke('restoreRange', $editable);
            handler.invoke('focus', $editable);
            handler.invoke('pasteHTML', $editable, pasteContent.html());
            $paste.empty();
          }
        }, 0);
      }
    };
  };

  return Clipboard;
});
<commit_msg>Code cleaning for clipboard.js 2.<commit_after>define([
  'summernote/core/list',
  'summernote/core/dom',
  'summernote/core/key',
  'summernote/core/agent'
], function (list, dom, key, agent) {
  var Clipboard = function (handler) {
    var $paste;

    this.attach = function (layoutInfo) {
      if (window.clipboardData || agent.isFF) {
        $paste = $('<div />').attr('contenteditable', true).css({
          position : 'absolute',
          left : -100000,
          opacity : 0
        });
        layoutInfo.editable().after($paste);
        $paste.on('paste', hPaste);

        layoutInfo.editable().on('keydown', function (e) {
          if (e.ctrlKey && e.keyCode === key.code.V) {
            handler.invoke('saveRange', layoutInfo.editable());
            $paste.focus();
          }
        });
      }

      layoutInfo.editable().on('paste', hPaste);
    };

    /**
     * paste clipboard image
     *
     * @param {Event} event
     */
    var hPaste = function (event) {
      var clipboardData = event.originalEvent.clipboardData;
      var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
      var $editable = layoutInfo.editable();

      if (clipboardData && clipboardData.items && clipboardData.items.length) {
        // using clipboardData case
        var item = list.head(clipboardData.items);
        if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
          handler.insertImages(layoutInfo, [item.getAsFile()]);
        }

        handler.invoke('editor.afterCommand', $editable);
      } else if ($paste && $editable.data('callbacks').onImageUpload) {
        // using dummy contenteditable: only can run if it has onImageUpload method
        setTimeout(function () {
          var node = $paste[0].firstChild;
          if (dom.isImg(node)) {
            handler.invoke('restoreRange', $editable);
            var dataURI = node.src;

            var decodedData = atob(dataURI.split(',')[1]);
            var array = new Uint8Array(decodedData.length);
            for (var i = 0; i < decodedData.length; i++) {
              array[i] = decodedData.charCodeAt(i);
            }

            var blob = new Blob([array], { type : 'image/png' });
            blob.name = 'clipboard.png';
            handler.invoke('focus', $editable);
            handler.insertImages(layoutInfo, [blob]);
            $paste.empty();
          } else {
            var pasteContent = $('<div />').html($paste.html());
            handler.invoke('restoreRange', $editable);
            handler.invoke('focus', $editable);
            handler.invoke('pasteHTML', $editable, pasteContent.html());
            $paste.empty();
          }
        }, 0);
      }
    };
  };

  return Clipboard;
});
<|endoftext|>


<commit_before>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
---
description: Creates a SplitView instances for all elements that have the css class .splitview (and children with .left_col and .right_col).
provides: [CCS.JFrame.SplitView]
requires: [/CCS.JFrame, Widgets/ART.SplitView]
script: CCS.JFrame.SplitView.js

...
*/

CCS.JFrame.addGlobalFilters({

	splitView: function(container) {
		if (!container.get('html').contains('splitview')) return;
		container.setStyle('overflow', 'hidden');
		//for all div.splitview containers, get their left and right column and instantiate an ART.SplitView
		//if the container has the class "resizable" then make it so
		//ditto for the foldable option
		//if the left or right columns have explicit style="width: Xpx" assignments
		//resize the side to match that statement; if both have it, the right one wins
		var splitviews = container.getElements('div.splitview').map(function(splitview){
			var left = splitview.getElement('.left_col');
			var right = splitview.getElement('.right_col');
			var top = splitview.getElement('.top_col');
			var bottom = splitview.getElement('.bottom_col');
			if (!(left && right) && !(top && bottom)) {
				dbug.warn('found split view element, but could not find top/botom or left/right; exiting');
				return;
			}
			var conf;
			if (left) {
				conf = {
					sides: ['left', 'right'],
					elements: {
						left: left,
						right: right
					},
					dimension: 'width'
				};
			} else {
				conf = {
					sides: ['top', 'bottom'],
					elements: {
						top: top,
						bottom: bottom
					},
					dimension: 'height'
				};
			}
			var inlineSize = {};
			conf.sides.each(function(side) {
				var size = conf.elements[side].style[conf.dimension];
				if (size) inlineSize[side] = size.toInt();
				conf.elements[side].setStyle(conf.dimension, 'auto');
			});

			var styles = {}, splitterHidden;
			var splitter = splitview.getElement('.splitter_col');
			if (splitter) {
				if (splitter.getStyle('display', 'none')) {
					splitterHidden = true;
					splitter.setStyle('display', 'block');
				}
				if (left) styles['splitter-width'] = splitter.getSize().x;
				else styles['splitter-height'] = splitter.getSize().y;
			}

			var whichSplit = left ? ART.SplitView : ART.SplitView.Vertical;
			var split = new whichSplit({
				resizable: splitview.hasClass("resizable"),
				foldable: splitview.hasClass("foldable"),
				splitterContent: splitview.getElement('.splitter_col'),
				styles: styles
			}).inject(this, splitview, 'after').draw();
			var sized;
			conf.sides.each(function(side) {
				split['set' + side.capitalize() + 'Content'](conf.elements[side]);
				split[side].addClass('save_scroll');
				if (sized) return;
				if (conf.elements[side].getStyle('display') == 'none') {
					split.fold(side, 0, splitterHidden, true);
					conf.elements[side].setStyle('display', 'block');
					sized = true;
				} else if (inlineSize[side]) {
					split['resize'+side.capitalize()](inlineSize[side]);
					sized = true;
				}
			});
			var classes = splitview.get('class').split(' ');
			splitview.destroy();
			classes.each(split.addClass, split);
			split.resizer = function(){
				if (this.parentWidget && this.parentWidget.contentSize) {
					var offsets = {
						x: splitview.get('data', 'split-offset-x', true),
						y: splitview.get('data', 'split-offset-y', true)
					};
					var w = this.parentWidget.contentSize.x;
					var h = this.parentWidget.contentSize.y;
					if (offsets.x) w = w - offsets.x;
					if (offsets.y) h = h - offsets.y;
					if (w != undefined && h != undefined) split.resize(w, h);
					else split.resizer.delay(1);
				} else {
					split.resizer.delay(1);
				}
			}.bind(this);
			this.addEvents({
				resize: split.resizer,
				show: split.resizer
			});
			split.resizer();
			return split;
		}, this);
		this.markForCleanup(function(){
			splitviews.each(function(splitview) {
				this.removeEvent('resize', splitview.resizer);
				splitview.eject();
			}, this);
		}.bind(this));

		return splitviews;
	}

});

(function(){

var getWidget = function(link) {
	var splitview = link.getParent('.splitview');
	if (!splitview) return;
	return splitview.get('widget');
};
CCS.JFrame.addGlobalLinkers({

	'[data-splitview-resize]': function(e, link){
		var widget = getWidget(link);
		if (!widget) return;
		e.stop();
		var resize = link.get('data', 'splitview-resize', true);
		if (!resize) return;
		var side;
		var sides = ['left', 'right', 'top', 'bottom'];
		for (key in resize) {
			if (sides.contains(key)) side = key;
		}
		widget.fold(side, resize[side], resize.hideSplitter).chain(partialPostFold.bind(this, [resize, e, link]));
	},

	'[data-splitview-toggle]': function(e, link){
		var widget = getWidget(link);
		if (!widget) return;
		e.stop();
		var resize = link.get('data', 'splitview-toggle', true);
		if (!resize) return;
		widget.toggle(resize.side, resize.hideSplitter).chain(partialPostFold.bind(this, [resize, e, link]));
	}

});

var partialPostFold = function(data, event, link){
	if (!$(document.body).hasChild(link)) return;
	if (data.partialRefresh) {
		if ($type(data.partialRefresh) == "string") link = new Element('a', { href: data.partialRefresh });
		this.invokeLinker('.ccs-fake_refresh', link, event);
	}
};

})();<commit_msg>HUE-36 elements that are inside elements with the [data-splitview-toggle] aren't interactive (like checkboxes) because the [data-splitview-toggle] linker calls event.stop(). They shouldn't stop propagation or default behavior of the event at all.<commit_after>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
---
description: Creates a SplitView instances for all elements that have the css class .splitview (and children with .left_col and .right_col).
provides: [CCS.JFrame.SplitView]
requires: [/CCS.JFrame, Widgets/ART.SplitView]
script: CCS.JFrame.SplitView.js

...
*/

CCS.JFrame.addGlobalFilters({

	splitView: function(container) {
		if (!container.get('html').contains('splitview')) return;
		container.setStyle('overflow', 'hidden');
		//for all div.splitview containers, get their left and right column and instantiate an ART.SplitView
		//if the container has the class "resizable" then make it so
		//ditto for the foldable option
		//if the left or right columns have explicit style="width: Xpx" assignments
		//resize the side to match that statement; if both have it, the right one wins
		var splitviews = container.getElements('div.splitview').map(function(splitview){
			var left = splitview.getElement('.left_col');
			var right = splitview.getElement('.right_col');
			var top = splitview.getElement('.top_col');
			var bottom = splitview.getElement('.bottom_col');
			if (!(left && right) && !(top && bottom)) {
				dbug.warn('found split view element, but could not find top/botom or left/right; exiting');
				return;
			}
			var conf;
			if (left) {
				conf = {
					sides: ['left', 'right'],
					elements: {
						left: left,
						right: right
					},
					dimension: 'width'
				};
			} else {
				conf = {
					sides: ['top', 'bottom'],
					elements: {
						top: top,
						bottom: bottom
					},
					dimension: 'height'
				};
			}
			var inlineSize = {};
			conf.sides.each(function(side) {
				var size = conf.elements[side].style[conf.dimension];
				if (size) inlineSize[side] = size.toInt();
				conf.elements[side].setStyle(conf.dimension, 'auto');
			});

			var styles = {}, splitterHidden;
			var splitter = splitview.getElement('.splitter_col');
			if (splitter) {
				if (splitter.getStyle('display', 'none')) {
					splitterHidden = true;
					splitter.setStyle('display', 'block');
				}
				if (left) styles['splitter-width'] = splitter.getSize().x;
				else styles['splitter-height'] = splitter.getSize().y;
			}

			var whichSplit = left ? ART.SplitView : ART.SplitView.Vertical;
			var split = new whichSplit({
				resizable: splitview.hasClass("resizable"),
				foldable: splitview.hasClass("foldable"),
				splitterContent: splitview.getElement('.splitter_col'),
				styles: styles
			}).inject(this, splitview, 'after').draw();
			var sized;
			conf.sides.each(function(side) {
				split['set' + side.capitalize() + 'Content'](conf.elements[side]);
				split[side].addClass('save_scroll');
				if (sized) return;
				if (conf.elements[side].getStyle('display') == 'none') {
					split.fold(side, 0, splitterHidden, true);
					conf.elements[side].setStyle('display', 'block');
					sized = true;
				} else if (inlineSize[side]) {
					split['resize'+side.capitalize()](inlineSize[side]);
					sized = true;
				}
			});
			var classes = splitview.get('class').split(' ');
			splitview.destroy();
			classes.each(split.addClass, split);
			split.resizer = function(){
				if (this.parentWidget && this.parentWidget.contentSize) {
					var offsets = {
						x: splitview.get('data', 'split-offset-x', true),
						y: splitview.get('data', 'split-offset-y', true)
					};
					var w = this.parentWidget.contentSize.x;
					var h = this.parentWidget.contentSize.y;
					if (offsets.x) w = w - offsets.x;
					if (offsets.y) h = h - offsets.y;
					if (w != undefined && h != undefined) split.resize(w, h);
					else split.resizer.delay(1);
				} else {
					split.resizer.delay(1);
				}
			}.bind(this);
			this.addEvents({
				resize: split.resizer,
				show: split.resizer
			});
			split.resizer();
			return split;
		}, this);
		this.markForCleanup(function(){
			splitviews.each(function(splitview) {
				this.removeEvent('resize', splitview.resizer);
				splitview.eject();
			}, this);
		}.bind(this));

		return splitviews;
	}

});

(function(){

var getWidget = function(link) {
	var splitview = link.getParent('.splitview');
	if (!splitview) return;
	return splitview.get('widget');
};
CCS.JFrame.addGlobalLinkers({

	'[data-splitview-resize]': function(e, link){
		var widget = getWidget(link);
		if (!widget) return;
		var resize = link.get('data', 'splitview-resize', true);
		if (!resize) return;
		var side;
		var sides = ['left', 'right', 'top', 'bottom'];
		for (key in resize) {
			if (sides.contains(key)) side = key;
		}
		widget.fold(side, resize[side], resize.hideSplitter).chain(partialPostFold.bind(this, [resize, e, link]));
	},

	'[data-splitview-toggle]': function(e, link){
		var widget = getWidget(link);
		if (!widget) return;
		var resize = link.get('data', 'splitview-toggle', true);
		if (!resize) return;
		widget.toggle(resize.side, resize.hideSplitter).chain(partialPostFold.bind(this, [resize, e, link]));
	}

});

var partialPostFold = function(data, event, link){
	if (!$(document.body).hasChild(link)) return;
	if (data.partialRefresh) {
		if ($type(data.partialRefresh) == "string") link = new Element('a', { href: data.partialRefresh });
		this.invokeLinker('.ccs-fake_refresh', link, event);
	}
};

})();<|endoftext|>


<commit_before><commit_msg>Visibility annotation and document getKeyDef, see phetsims/scenery#1053<commit_after><|endoftext|>