<commit_before>// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.

(function ($) {

  console.log('DatePicker executed');

  /**
   * @param {object} options DatePicker options
   * @param {array} options.optionMonths An array of month abbreviations for the options grid
   * @param {string} options.label A label for the DatePicker
   * @param {string} options.placeholderText Placeholder text for the DatePicker textfield
   */
  $.fn.DatePicker = function (options) {

    var datePicker;
    var self = this;
    var optionMonths = options && options.optionMonths || ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    var label = options && options.label || "Start Date";
    var placeholderText = options && options.placeholderText || "Select a date";

    /** check if the PickaDate plugin exists, if not load the plugin */
    if (!$().pickadate) {
      var firstScript = document.getElementsByTagName("script")[0];
      var script = document.createElement("script");
      script.onload = returnDatePicker;
      script.src = "PickaDate.js";
      firstScript.parentNode.insertBefore(script, firstScript);
    } else {
      datePicker = returnDatePicker();
    }

    function returnDatePicker() {
      /** Iterate through each date picker provided. */
      return self.each(function () {

        var $datePicker = $(this);

        /**create the body of the datepicker */
        appendElements($datePicker, optionMonths);

        /** insert label and placeholder text */
        $datePicker.find('.ms-Label').text(label);
        $datePicker.find('.ms-TextField-field').attr("placeholder", placeholderText + "...");

        /** Set up variables and run the Pickadate plugin. */
        var $dateField = $datePicker.find('.ms-TextField-field').pickadate({
          // Strings and translations.
          weekdaysShort: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],

          // Don't render the buttons
          today: '',
          clear: '',
          close: '',

          // Events
          onStart: function() {
            initCustomView($datePicker);
          },

          // Classes
          klass: {

            // The element states
            input: 'ms-DatePicker-input',
            active: 'ms-DatePicker-input--active',

            // The root picker and states
            picker: 'ms-DatePicker-picker',
            opened: 'ms-DatePicker-picker--opened',
            focused: 'ms-DatePicker-picker--focused',

            // The picker holder
            holder: 'ms-DatePicker-holder',

            // The picker frame, wrapper, and box
            frame: 'ms-DatePicker-frame',
            wrap: 'ms-DatePicker-wrap',
            box: 'ms-DatePicker-dayPicker',

            // The picker header
            header: 'ms-DatePicker-header',

            // Month & year labels
            month: 'ms-DatePicker-month',
            year: 'ms-DatePicker-year',

            // Table of dates
            table: 'ms-DatePicker-table',

            // Weekday labels
            weekdays: 'ms-DatePicker-weekday',

            // Day states
            day: 'ms-DatePicker-day',
            disabled: 'ms-DatePicker-day--disabled',
            selected: 'ms-DatePicker-day--selected',
            now: 'ms-DatePicker-day--today',
            infocus: 'ms-DatePicker-day--infocus',
            outfocus: 'ms-DatePicker-day--outfocus'
          }
        });
        var $picker = $dateField.pickadate('picker');

        /** Respond to built-in picker events. */
        $picker.on({
          render: function() {
            updateCustomView($datePicker);
          },
          open: function() {
            scrollUp($datePicker);
          }
        });

      });
    }

    return datePicker;
  };

  /**
   * Create the body of the DatePicker plugin and
   * append it to the date picker element
   * @param {object} $datePicker JQuery object
   * @param {array} optionMonths
   */
  function appendElements($datePicker, optionMonths) {
    var elements = '
';
    elements += '';
    elements += '';
    elements += '<input class="ms-TextField-field" type="text">';
    elements += '
';
    elements += '
';
    elements += '';
    elements += '';
    elements += '

';
    elements += '
';
    elements += 'Go to today';
    elements += '
';
    elements += '
';
    elements += '
';
    elements += '';
    elements += '';
    elements += '
';
    elements += '

';
    elements += '
';
    elements += '
';
    elements += '

';
    elements += '
';
    elements += '
';
    elements += '';
    elements += '';
    elements += '

';
    $datePicker.append(elements);
    $datePicker.find('.ms-DatePicker-optionGrid').append(createMonthOptions(optionMonths));
  }
  /**
   * creates month elements for the month grid
   * @param {array} optionMonths
   * @returns {string}
   */
  function createMonthOptions(optionMonths) {
    var i = 0;
    var content = "";
    for(i; i < 12; i++) {
      content += '' + optionMonths[i] + '';
    }
    return content;
  }
  /**
   * After the Pickadate plugin starts, this function
   * adds additional controls to the picker view.
   */
  function initCustomView($datePicker) {

    /** Get some variables ready. */
    var $monthControls = $datePicker.find('.ms-DatePicker-monthComponents');
    var $goToday = $datePicker.find('.ms-DatePicker-goToday');
    var $dayPicker = $datePicker.find('.ms-DatePicker-dayPicker');
    var $monthPicker = $datePicker.find('.ms-DatePicker-monthPicker');
    var $yearPicker = $datePicker.find('.ms-DatePicker-yearPicker');
    var $pickerWrapper = $datePicker.find('.ms-DatePicker-wrap');
    var $picker = $datePicker.find('.ms-TextField-field').pickadate('picker');

    /** Move the month picker into position. */
    $monthControls.appendTo($pickerWrapper);
    $goToday.appendTo($pickerWrapper);
    $monthPicker.appendTo($pickerWrapper);
    $yearPicker.appendTo($pickerWrapper);

    /** Update the custom view. */
    updateCustomView($datePicker);

    /** Move back one month. */
    $monthControls.on('click', '.js-prevMonth', function(event) {
      event.preventDefault();
      var newMonth = $picker.get('highlight').month - 1;
      changeHighlightedDate($picker, null, newMonth, null);
    });

    /** Move ahead one month. */
    $monthControls.on('click', '.js-nextMonth', function(event) {
      event.preventDefault();
      var newMonth = $picker.get('highlight').month + 1;
      changeHighlightedDate($picker, null, newMonth, null);
    });

    /** Move back one year. */
    $monthPicker.on('click', '.js-prevYear', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year - 1;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Move ahead one year. */
    $monthPicker.on('click', '.js-nextYear', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year + 1;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Move back one decade. */
    $yearPicker.on('click', '.js-prevDecade', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year - 10;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Move ahead one decade. */
    $yearPicker.on('click', '.js-nextDecade', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year + 10;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Go to the current date, shown in the day picking view. */
    $goToday.click(function(event) {
      event.preventDefault();

      /** Select the current date, while keeping the picker open. */
      var now = new Date();
      $picker.set('select', [now.getFullYear(), now.getMonth(), now.getDate()]);

      /** Switch to the default (calendar) view. */
      $datePicker.removeClass('is-pickingMonths').removeClass('is-pickingYears');

    });

    /** Change the highlighted month. */
    $monthPicker.on('click', '.js-changeDate', function(event) {
      event.preventDefault();

      /** Get the requested date from the data attributes. */
      var newYear = $(this).attr('data-year');
      var newMonth = $(this).attr('data-month');
      var newDay = $(this).attr('data-day');

      /** Update the date. */
      changeHighlightedDate($picker, newYear, newMonth, newDay);

      /** If we've been in the "picking months" state on mobile, remove that state so we show the calendar again. */
      if ($datePicker.hasClass('is-pickingMonths')) {
        $datePicker.removeClass('is-pickingMonths');
      }
    });

    /** Change the highlighted year. */
    $yearPicker.on('click', '.js-changeDate', function(event) {
      event.preventDefault();

      /** Get the requested date from the data attributes. */
      var newYear = $(this).attr('data-year');
      var newMonth = $(this).attr('data-month');
      var newDay = $(this).attr('data-day');

      /** Update the date. */
      changeHighlightedDate($picker, newYear, newMonth, newDay);

      /** If we've been in the "picking years" state on mobile, remove that state so we show the calendar again. */
      if ($datePicker.hasClass('is-pickingYears')) {
        $datePicker.removeClass('is-pickingYears');
      }
    });

    /** Switch to the default state. */
    $monthPicker.on('click', '.js-showDayPicker', function(event) {
      $datePicker.removeClass('is-pickingMonths');
      $datePicker.removeClass('is-pickingYears');
    });

    /** Switch to the is-pickingMonths state. */
    $monthControls.on('click', '.js-showMonthPicker', function(event) {
      $datePicker.toggleClass('is-pickingMonths');
    });

    /** Switch to the is-pickingYears state. */
    $monthPicker.on('click', '.js-showYearPicker', function(event) {
      $datePicker.toggleClass('is-pickingYears');
    });

  }

  /** Change the highlighted date. */
  function changeHighlightedDate($picker, newYear, newMonth, newDay) {

    /** All variables are optional. If not provided, default to the current value. */
    if (newYear == null) {
      newYear = $picker.get('highlight').year;
    }
    if (newMonth == null) {
      newMonth = $picker.get('highlight').month;
    }
    if (newDay == null) {
      newDay = $picker.get('highlight').date;
    }

    /** Update it. */
    $picker.set('highlight', [newYear, newMonth, newDay]);

  }

  /** Whenever the picker renders, do our own rendering on the custom controls. */
  function updateCustomView($datePicker) {
    /** Get some variables ready. */
    var $monthPicker = $datePicker.find('.ms-DatePicker-monthPicker');
    var $yearPicker = $datePicker.find('.ms-DatePicker-yearPicker');
    var $pickerWrapper = $datePicker.find('.ms-DatePicker-wrap');
    var $picker = $datePicker.find('.ms-TextField-field').pickadate('picker');

    /** Set the correct year. */
    $monthPicker.find('.ms-DatePicker-currentYear').text($picker.get('view').year);

    /** Highlight the current month. */
    $monthPicker.find('.ms-DatePicker-monthOption').removeClass('is-highlighted')
    $monthPicker.find('.ms-DatePicker-monthOption[data-month="' + $picker.get('highlight').month + '"]').addClass('is-highlighted');

    /** Generate the grid of years for the year picker view. */

      // Start by removing any existing generated output. */
    $yearPicker.find('.ms-DatePicker-currentDecade').remove();
    $yearPicker.find('.ms-DatePicker-optionGrid').remove();

    // Generate the output by going through the years.
    var startingYear = $picker.get('highlight').year - 11;
    var decadeText = startingYear + " - " + (startingYear + 11);
    var output = '
' + decadeText + '
';
    output += '
';
    for (year = startingYear; year < (startingYear + 12); year++) {
      output += '' + year +'';
    }
    output += '
';

    // Output the title and grid of years generated above.
    $yearPicker.append(output);

    /** Highlight the current year. */
    $yearPicker.find('.ms-DatePicker-yearOption').removeClass('is-highlighted')
    $yearPicker.find('.ms-DatePicker-yearOption[data-year="' + $picker.get('highlight').year + '"]').addClass('is-highlighted');
  }

  /** Scroll the page up so that the field the date picker is attached to is at the top. */
  function scrollUp($datePicker) {
    $('html, body').animate({
      scrollTop: $datePicker.offset().top
    }, 367);
  }

})(jQuery);<commit_msg>- Removed console log<commit_after>// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.

(function ($) {

  /**
   * @param {object} options DatePicker options
   * @param {array} options.optionMonths An array of month abbreviations for the options grid
   * @param {string} options.label A label for the DatePicker
   * @param {string} options.placeholderText Placeholder text for the DatePicker textfield
   */
  $.fn.DatePicker = function (options) {

    var datePicker;
    var self = this;
    var optionMonths = options && options.optionMonths || ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    var label = options && options.label || "Start Date";
    var placeholderText = options && options.placeholderText || "Select a date";

    /** check if the PickaDate plugin exists, if not load the plugin */
    if (!$().pickadate) {
      var firstScript = document.getElementsByTagName("script")[0];
      var script = document.createElement("script");
      script.onload = returnDatePicker;
      script.src = "PickaDate.js";
      firstScript.parentNode.insertBefore(script, firstScript);
    } else {
      datePicker = returnDatePicker();
    }

    function returnDatePicker() {
      /** Iterate through each date picker provided. */
      return self.each(function () {

        var $datePicker = $(this);

        /**create the body of the datepicker */
        appendElements($datePicker, optionMonths);

        /** insert label and placeholder text */
        $datePicker.find('.ms-Label').text(label);
        $datePicker.find('.ms-TextField-field').attr("placeholder", placeholderText + "...");

        /** Set up variables and run the Pickadate plugin. */
        var $dateField = $datePicker.find('.ms-TextField-field').pickadate({
          // Strings and translations.
          weekdaysShort: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],

          // Don't render the buttons
          today: '',
          clear: '',
          close: '',

          // Events
          onStart: function() {
            initCustomView($datePicker);
          },

          // Classes
          klass: {

            // The element states
            input: 'ms-DatePicker-input',
            active: 'ms-DatePicker-input--active',

            // The root picker and states
            picker: 'ms-DatePicker-picker',
            opened: 'ms-DatePicker-picker--opened',
            focused: 'ms-DatePicker-picker--focused',

            // The picker holder
            holder: 'ms-DatePicker-holder',

            // The picker frame, wrapper, and box
            frame: 'ms-DatePicker-frame',
            wrap: 'ms-DatePicker-wrap',
            box: 'ms-DatePicker-dayPicker',

            // The picker header
            header: 'ms-DatePicker-header',

            // Month & year labels
            month: 'ms-DatePicker-month',
            year: 'ms-DatePicker-year',

            // Table of dates
            table: 'ms-DatePicker-table',

            // Weekday labels
            weekdays: 'ms-DatePicker-weekday',

            // Day states
            day: 'ms-DatePicker-day',
            disabled: 'ms-DatePicker-day--disabled',
            selected: 'ms-DatePicker-day--selected',
            now: 'ms-DatePicker-day--today',
            infocus: 'ms-DatePicker-day--infocus',
            outfocus: 'ms-DatePicker-day--outfocus'
          }
        });
        var $picker = $dateField.pickadate('picker');

        /** Respond to built-in picker events. */
        $picker.on({
          render: function() {
            updateCustomView($datePicker);
          },
          open: function() {
            scrollUp($datePicker);
          }
        });

      });
    }

    return datePicker;
  };

  /**
   * Create the body of the DatePicker plugin and
   * append it to the date picker element
   * @param {object} $datePicker JQuery object
   * @param {array} optionMonths
   */
  function appendElements($datePicker, optionMonths) {
    var elements = '
';
    elements += '';
    elements += '';
    elements += '<input class="ms-TextField-field" type="text">';
    elements += '
';
    elements += '
';
    elements += '';
    elements += '';
    elements += '

';
    elements += '
';
    elements += 'Go to today';
    elements += '
';
    elements += '
';
    elements += '
';
    elements += '';
    elements += '';
    elements += '
';
    elements += '

';
    elements += '
';
    elements += '
';
    elements += '

';
    elements += '
';
    elements += '
';
    elements += '';
    elements += '';
    elements += '

';
    $datePicker.append(elements);
    $datePicker.find('.ms-DatePicker-optionGrid').append(createMonthOptions(optionMonths));
  }
  /**
   * creates month elements for the month grid
   * @param {array} optionMonths
   * @returns {string}
   */
  function createMonthOptions(optionMonths) {
    var i = 0;
    var content = "";
    for(i; i < 12; i++) {
      content += '' + optionMonths[i] + '';
    }
    return content;
  }
  /**
   * After the Pickadate plugin starts, this function
   * adds additional controls to the picker view.
   */
  function initCustomView($datePicker) {

    /** Get some variables ready. */
    var $monthControls = $datePicker.find('.ms-DatePicker-monthComponents');
    var $goToday = $datePicker.find('.ms-DatePicker-goToday');
    var $dayPicker = $datePicker.find('.ms-DatePicker-dayPicker');
    var $monthPicker = $datePicker.find('.ms-DatePicker-monthPicker');
    var $yearPicker = $datePicker.find('.ms-DatePicker-yearPicker');
    var $pickerWrapper = $datePicker.find('.ms-DatePicker-wrap');
    var $picker = $datePicker.find('.ms-TextField-field').pickadate('picker');

    /** Move the month picker into position. */
    $monthControls.appendTo($pickerWrapper);
    $goToday.appendTo($pickerWrapper);
    $monthPicker.appendTo($pickerWrapper);
    $yearPicker.appendTo($pickerWrapper);

    /** Update the custom view. */
    updateCustomView($datePicker);

    /** Move back one month. */
    $monthControls.on('click', '.js-prevMonth', function(event) {
      event.preventDefault();
      var newMonth = $picker.get('highlight').month - 1;
      changeHighlightedDate($picker, null, newMonth, null);
    });

    /** Move ahead one month. */
    $monthControls.on('click', '.js-nextMonth', function(event) {
      event.preventDefault();
      var newMonth = $picker.get('highlight').month + 1;
      changeHighlightedDate($picker, null, newMonth, null);
    });

    /** Move back one year. */
    $monthPicker.on('click', '.js-prevYear', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year - 1;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Move ahead one year. */
    $monthPicker.on('click', '.js-nextYear', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year + 1;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Move back one decade. */
    $yearPicker.on('click', '.js-prevDecade', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year - 10;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Move ahead one decade. */
    $yearPicker.on('click', '.js-nextDecade', function(event) {
      event.preventDefault();
      var newYear = $picker.get('highlight').year + 10;
      changeHighlightedDate($picker, newYear, null, null);
    });

    /** Go to the current date, shown in the day picking view. */
    $goToday.click(function(event) {
      event.preventDefault();

      /** Select the current date, while keeping the picker open. */
      var now = new Date();
      $picker.set('select', [now.getFullYear(), now.getMonth(), now.getDate()]);

      /** Switch to the default (calendar) view. */
      $datePicker.removeClass('is-pickingMonths').removeClass('is-pickingYears');

    });

    /** Change the highlighted month. */
    $monthPicker.on('click', '.js-changeDate', function(event) {
      event.preventDefault();

      /** Get the requested date from the data attributes. */
      var newYear = $(this).attr('data-year');
      var newMonth = $(this).attr('data-month');
      var newDay = $(this).attr('data-day');

      /** Update the date. */
      changeHighlightedDate($picker, newYear, newMonth, newDay);

      /** If we've been in the "picking months" state on mobile, remove that state so we show the calendar again. */
      if ($datePicker.hasClass('is-pickingMonths')) {
        $datePicker.removeClass('is-pickingMonths');
      }
    });

    /** Change the highlighted year. */
    $yearPicker.on('click', '.js-changeDate', function(event) {
      event.preventDefault();

      /** Get the requested date from the data attributes. */
      var newYear = $(this).attr('data-year');
      var newMonth = $(this).attr('data-month');
      var newDay = $(this).attr('data-day');

      /** Update the date. */
      changeHighlightedDate($picker, newYear, newMonth, newDay);

      /** If we've been in the "picking years" state on mobile, remove that state so we show the calendar again. */
      if ($datePicker.hasClass('is-pickingYears')) {
        $datePicker.removeClass('is-pickingYears');
      }
    });

    /** Switch to the default state. */
    $monthPicker.on('click', '.js-showDayPicker', function(event) {
      $datePicker.removeClass('is-pickingMonths');
      $datePicker.removeClass('is-pickingYears');
    });

    /** Switch to the is-pickingMonths state. */
    $monthControls.on('click', '.js-showMonthPicker', function(event) {
      $datePicker.toggleClass('is-pickingMonths');
    });

    /** Switch to the is-pickingYears state. */
    $monthPicker.on('click', '.js-showYearPicker', function(event) {
      $datePicker.toggleClass('is-pickingYears');
    });

  }

  /** Change the highlighted date. */
  function changeHighlightedDate($picker, newYear, newMonth, newDay) {

    /** All variables are optional. If not provided, default to the current value. */
    if (newYear == null) {
      newYear = $picker.get('highlight').year;
    }
    if (newMonth == null) {
      newMonth = $picker.get('highlight').month;
    }
    if (newDay == null) {
      newDay = $picker.get('highlight').date;
    }

    /** Update it. */
    $picker.set('highlight', [newYear, newMonth, newDay]);

  }

  /** Whenever the picker renders, do our own rendering on the custom controls. */
  function updateCustomView($datePicker) {
    /** Get some variables ready. */
    var $monthPicker = $datePicker.find('.ms-DatePicker-monthPicker');
    var $yearPicker = $datePicker.find('.ms-DatePicker-yearPicker');
    var $pickerWrapper = $datePicker.find('.ms-DatePicker-wrap');
    var $picker = $datePicker.find('.ms-TextField-field').pickadate('picker');

    /** Set the correct year. */
    $monthPicker.find('.ms-DatePicker-currentYear').text($picker.get('view').year);

    /** Highlight the current month. */
    $monthPicker.find('.ms-DatePicker-monthOption').removeClass('is-highlighted')
    $monthPicker.find('.ms-DatePicker-monthOption[data-month="' + $picker.get('highlight').month + '"]').addClass('is-highlighted');

    /** Generate the grid of years for the year picker view. */

      // Start by removing any existing generated output. */
    $yearPicker.find('.ms-DatePicker-currentDecade').remove();
    $yearPicker.find('.ms-DatePicker-optionGrid').remove();

    // Generate the output by going through the years.
    var startingYear = $picker.get('highlight').year - 11;
    var decadeText = startingYear + " - " + (startingYear + 11);
    var output = '
' + decadeText + '
';
    output += '
';
    for (year = startingYear; year < (startingYear + 12); year++) {
      output += '' + year +'';
    }
    output += '
';

    // Output the title and grid of years generated above.
    $yearPicker.append(output);

    /** Highlight the current year. */
    $yearPicker.find('.ms-DatePicker-yearOption').removeClass('is-highlighted')
    $yearPicker.find('.ms-DatePicker-yearOption[data-year="' + $picker.get('highlight').year + '"]').addClass('is-highlighted');
  }

  /** Scroll the page up so that the field the date picker is attached to is at the top. */
  function scrollUp($datePicker) {
    $('html, body').animate({
      scrollTop: $datePicker.offset().top
    }, 367);
  }

})(jQuery);<|endoftext|>


<commit_before>//tickets.js: Client for the zendesk API.

var util        = require('util'),
    Client      = require('./client').Client,
    defaultUser = require('./helpers').defaultUser;

var Tickets = exports.Tickets = function (options) {
  this.jsonAPINames = ['tickets', 'ticket', 'audits'];
  this.sideLoadMap = [
    { field: 'assignee_id',     name: 'assignee',     dataset: 'users'},
    { field: 'requester_id',    name: 'requester',    dataset: 'users'},
    { field: 'submitter_id',    name: 'submitter',    dataset: 'users'},
    { field: 'organization_id', name: 'organization', dataset: 'organizations'},
    { field: 'id',              name: 'sharing_agreements',    dataset: 'sharing_agreements'},
  ];
  Client.call(this, options);
};

// Inherit from Client base object
util.inherits(Tickets, Client);

// ######################################################## Tickets
// ====================================== Listing Tickets
Tickets.prototype.list = function (cb) {
  this.requestAll('GET', ['tickets'], cb);//all
};

Tickets.prototype.listByOrganization = function (orgID, cb) {
  this.requestAll('GET', ['organizations', orgID, 'tickets'], cb);//all
};

Tickets.prototype.listByUserRequested = function (userID, cb) {
  this.requestAll('GET', ['users', userID, 'tickets', 'requested'], cb);//all
};

Tickets.prototype.listByUserCCD = function (userID, cb) {
  this.requestAll('GET', ['users', userID, 'tickets', 'ccd'], cb);//all
};

Tickets.prototype.listRecent = function (cb) {
  this.requestAll('GET', ['tickets', 'recent'], cb);//all?
};

Tickets.prototype.listCollaborators = function (ticketID, cb) {
  this.requestAll('GET', ['tickets', ticketID, 'collaborators'],  cb);//all?
};

Tickets.prototype.listIncidents = function (ticketID, cb) {
  this.requestAll('GET', ['tickets', ticketID, 'incidents'],  cb);//all
};

Tickets.prototype.listMetrics = function (ticketID, cb) {
  this.request('GET', ['tickets', ticketID, 'metrics'],  cb);//all
};

// ====================================== Viewing Tickets
Tickets.prototype.show = function (ticketID, cb) {
  this.request('GET', ['tickets', ticketID], cb);
};

Tickets.prototype.showMany = function (ticket_ids, cb) {
  this.request('GET', ['tickets', 'show_many', '?ids=' + ticket_ids.toString()], cb);
};

// ====================================== Creating Tickets
Tickets.prototype.create = function (ticket, cb) {
  this.request('POST', ['tickets'], ticket,  cb);
};

// ====================================== Updating Tickets
Tickets.prototype.update = function (ticketID, ticket, cb) {
  this.request('PUT', ['tickets', ticketID], ticket,  cb);
};

Tickets.prototype.updateMany = function (ticket_ids, ticket, cb) {
  this.request('PUT', ['tickets', 'update_many', '?ids=' + ticket_ids.toString()], ticket,  cb);
};

// ====================================== Deleting Tickets
Tickets.prototype.delete = function (ticketID, cb) {
  this.request('DELETE', ['tickets', ticketID],  cb);
};

Tickets.prototype.deleteMany = function (ticket_ids, cb) {
  this.request('DELETE', ['tickets', 'destroy_many', '?ids=' + ticket_ids.toString()],  cb);
};

// ====================================== Merging tickets
Tickets.prototype.merge = function (ticketID, mergedTicket, cb) {
  this.request('POST', ['tickets', ticketID, 'merge'], mergedTicket, cb);
};

// ######################################################## Ticket export (max 1000 tickets per request in 5 min intrvals)
// ====================================== Ticket Export
Tickets.prototype.export = function (startTime, cb) {
  this.request('GET', ['exports', 'tickets', {start_time: startTime}],  cb);
};

// ====================================== Ticket Export Sample (max 50 tickets per request)
Tickets.prototype.exportSample = function (startTime, options) {
  this.request('GET', ['exports', 'tickets', 'sample', {start_time: startTime}],  cb);
};

//  ====================================== New Incremental Ticket Export
Tickets.prototype.incremental = function (startTime, cb) {
  this.request('GET', ['incremental', 'tickets', {start_time: startTime}],  cb);
};
//  ====================================== New Incremental Ticket Export Sample
Tickets.prototype.incrementalSample = function (startTime, cb) {
  this.request('GET', ['incremental', 'tickets', 'sample', {start_time: startTime}],  cb);
};

// ====================================== Listing Ticket Comments
Tickets.prototype.getComments = function (ticketID, cb) {
	this.requestAll('GET', ['tickets', ticketID, 'comments'],  cb);
};

// ######################################################## Ticket Audits

// ====================================== Listing Audits
Tickets.prototype.exportAudit = function (ticketID, cb) {
  this.requestAll('GET', ['tickets', ticketID, 'audits'],  cb);
};

<commit_msg>Add PUT tickets/{id}/tags.json<commit_after>//tickets.js: Client for the zendesk API.

var util        = require('util'),
    Client      = require('./client').Client,
    defaultUser = require('./helpers').defaultUser;

var Tickets = exports.Tickets = function (options) {
  this.jsonAPINames = ['tickets', 'ticket', 'audits'];
  this.sideLoadMap = [
    { field: 'assignee_id',     name: 'assignee',     dataset: 'users'},
    { field: 'requester_id',    name: 'requester',    dataset: 'users'},
    { field: 'submitter_id',    name: 'submitter',    dataset: 'users'},
    { field: 'organization_id', name: 'organization', dataset: 'organizations'},
    { field: 'id',              name: 'sharing_agreements',    dataset: 'sharing_agreements'},
  ];
  Client.call(this, options);
};

// Inherit from Client base object
util.inherits(Tickets, Client);

// ######################################################## Tickets
// ====================================== Listing Tickets
Tickets.prototype.list = function (cb) {
  this.requestAll('GET', ['tickets'], cb);//all
};

Tickets.prototype.listByOrganization = function (orgID, cb) {
  this.requestAll('GET', ['organizations', orgID, 'tickets'], cb);//all
};

Tickets.prototype.listByUserRequested = function (userID, cb) {
  this.requestAll('GET', ['users', userID, 'tickets', 'requested'], cb);//all
};

Tickets.prototype.listByUserCCD = function (userID, cb) {
  this.requestAll('GET', ['users', userID, 'tickets', 'ccd'], cb);//all
};

Tickets.prototype.listRecent = function (cb) {
  this.requestAll('GET', ['tickets', 'recent'], cb);//all?
};

Tickets.prototype.listCollaborators = function (ticketID, cb) {
  this.requestAll('GET', ['tickets', ticketID, 'collaborators'],  cb);//all?
};

Tickets.prototype.listIncidents = function (ticketID, cb) {
  this.requestAll('GET', ['tickets', ticketID, 'incidents'],  cb);//all
};

Tickets.prototype.listMetrics = function (ticketID, cb) {
  this.request('GET', ['tickets', ticketID, 'metrics'],  cb);//all
};

// ====================================== Viewing Tickets
Tickets.prototype.show = function (ticketID, cb) {
  this.request('GET', ['tickets', ticketID], cb);
};

Tickets.prototype.showMany = function (ticket_ids, cb) {
  this.request('GET', ['tickets', 'show_many', '?ids=' + ticket_ids.toString()], cb);
};

// ====================================== Creating Tickets
Tickets.prototype.create = function (ticket, cb) {
  this.request('POST', ['tickets'], ticket,  cb);
};

// ====================================== Updating Tickets
Tickets.prototype.update = function (ticketID, ticket, cb) {
  this.request('PUT', ['tickets', ticketID], ticket,  cb);
};

Tickets.prototype.updateMany = function (ticket_ids, ticket, cb) {
  this.request('PUT', ['tickets', 'update_many', '?ids=' + ticket_ids.toString()], ticket,  cb);
};

// ====================================== Deleting Tickets
Tickets.prototype.delete = function (ticketID, cb) {
  this.request('DELETE', ['tickets', ticketID],  cb);
};

Tickets.prototype.deleteMany = function (ticket_ids, cb) {
  this.request('DELETE', ['tickets', 'destroy_many', '?ids=' + ticket_ids.toString()],  cb);
};

// ====================================== Merging tickets
Tickets.prototype.merge = function (ticketID, mergedTicket, cb) {
  this.request('POST', ['tickets', ticketID, 'merge'], mergedTicket, cb);
};

// ######################################################## Ticket export (max 1000 tickets per request in 5 min intrvals)
// ====================================== Ticket Export
Tickets.prototype.export = function (startTime, cb) {
  this.request('GET', ['exports', 'tickets', {start_time: startTime}],  cb);
};

// ====================================== Ticket Export Sample (max 50 tickets per request)
Tickets.prototype.exportSample = function (startTime, options) {
  this.request('GET', ['exports', 'tickets', 'sample', {start_time: startTime}],  cb);
};

//  ====================================== New Incremental Ticket Export
Tickets.prototype.incremental = function (startTime, cb) {
  this.request('GET', ['incremental', 'tickets', {start_time: startTime}],  cb);
};
//  ====================================== New Incremental Ticket Export Sample
Tickets.prototype.incrementalSample = function (startTime, cb) {
  this.request('GET', ['incremental', 'tickets', 'sample', {start_time: startTime}],  cb);
};

// ====================================== Listing Ticket Comments
Tickets.prototype.getComments = function (ticketID, cb) {
	this.requestAll('GET', ['tickets', ticketID, 'comments'],  cb);
};

// ######################################################## Ticket Audits

// ====================================== Listing Audits
Tickets.prototype.exportAudit = function (ticketID, cb) {
  this.requestAll('GET', ['tickets', ticketID, 'audits'],  cb);
};

// ######################################################## Ticket Tags

// ====================================== Add Tags to Ticket
Tickets.prototype.addTags = function (ticketID, tags, cb) {
  this.requestAll('PUT', ['tickets', ticketID, 'tags'], tags, cb);
};
<|endoftext|>


<commit_before>var Scroll = {
  positions: {},
  history: [],
  historyIndex: 0,
};

const NON_SCROLLABLE     = 0,
      SCROLLABLE_Y_DOWN  = 1,
      SCROLLABLE_Y_UP    = 2,
      SCROLLABLE_X_RIGHT = 4,
      SCROLLABLE_X_LEFT  = 8,
      SCROLLABLE = SCROLLABLE_X_LEFT | SCROLLABLE_X_RIGHT |
                   SCROLLABLE_Y_UP | SCROLLABLE_Y_DOWN;
// const SCROLLABLE_Y = SCROLLABLE_Y_UP   | SCROLLABLE_Y_DOWN,
//       SCROLLABLE_X = SCROLLABLE_X_LEFT | SCROLLABLE_X_RIGHT;

var scrollingElement = (function() {
  function getScrollType(elem) {
    var cs = getComputedStyle(elem);
    var st = NON_SCROLLABLE;
    if (cs.overflow === 'hidden')
      return st;
    if (cs.overflowX !== 'hidden' &&
        elem.offsetHeight > elem.clientHeight &&
        elem.scrollWidth > elem.clientWidth) {
      if (elem.scrollLeft > 0)
        st |= SCROLLABLE_X_LEFT;
      if (elem.scrollLeft + elem.clientWidth < elem.scrollWidth)
        st |= SCROLLABLE_X_RIGHT;
    }
    if (cs.overflowY !== 'hidden' &&
        elem.offsetWidth > elem.clientWidth &&
        elem.scrollHeight > elem.clientHeight) {
      if (elem.scrollTop > 0)
        st |= SCROLLABLE_Y_UP;
      if (elem.scrollTop + elem.clientHeight < elem.scrollHeight)
        st |= SCROLLABLE_Y_DOWN;
    }
    return st;
  }

  var lastActiveElem = null,
      lastScrollElem = null,
      clickFocus = false;

  window.resetScrollFocus = function() {
    clickFocus = false;
  };

  document.addEventListener('mousedown', function(event) {
    if (!event.isTrusted)
      return true;
    clickFocus = true;
    lastActiveElem = event.srcElement;
  });

  return function scrollingElement(dir) {
    var elem;
    if (clickFocus) {
      elem = lastActiveElem;
    } else {
      elem = lastActiveElem = document.activeElement;
    }
    if (elem === null)
      return null;
    return (function climb(elem) {
      if (elem === null)
        return lastScrollElem || document.scrollingElement;
      if (elem === document.scrollingElement)
        return elem;
      var st = getScrollType(elem);
      return st & dir ? elem : climb(elem.parentElement);
    })(elem);
  };
})();

function $scrollBy(elem, x, y) {
  elem.scrollLeft += x;
  elem.scrollTop += y;
}
function $scrollTo(elem, x, y) {
  if (x !== null)
    elem.scrollLeft = x;
  if (y !== null)
    elem.scrollTop = y;
}

(function($) {

  var animationYFrame, animationXFrame,
      scrollXFunction, scrollYFunction,
      scrollElem, scrollXElem,
      lastX, lastY;
  var holdKeyScroll = false;

  var easeFn = function(t, b, c, d) {
    return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
  };

  var timeFn = typeof window.performance === 'undefined' ?
    Date.now : performance.now.bind(performance);

  var scroll = {
    x0:   0, // starting x position
    x1:   0, // ending x position
    xc:   0, // delta-x during scroll
    tx:   0, // delta-t
    txo:  0, // last time measurement
    dx:   0, // x-duration
    y0:   0,
    y1:   0,
    yc:   0,
    ty:   0,
    tyo:  0,
    dy:   0,
    callback: null,
  };
  var scrollx = Object.clone(scroll);

  scrollYFunction = function() {
    var delta = easeFn(scroll.ty, scroll.y0, scroll.y1 - scroll.y0, scroll.dy);
    var time = timeFn();
    scroll.yc = delta;
    scroll.ty += time - scroll.tyo;
    scroll.tyo = time;
    $scrollTo(scrollElem, null, delta);
    if (!holdKeyScroll && scroll.ty <= scroll.dy) {
      animationYFrame = $.requestAnimationFrame(scrollYFunction);
    } else {
      $.cancelAnimationFrame(animationYFrame);
      animationYFrame = null;
      $scrollTo(scrollElem, null, scroll.y1);
      scroll.y0 = scroll.y1 = scroll.yc = scroll.ty = 0;
      if (scroll.callback)
        scroll.callback();
    }
  };

  scrollXFunction = function() {
    var delta = easeFn(scrollx.tx, scrollx.x0, scrollx.x1 - scrollx.x0, scrollx.dx);
    var time = timeFn();
    scrollx.xc = delta;
    scrollx.tx += time - scrollx.txo;
    scrollx.txo = time;
    $scrollTo(scrollXElem, delta, null);
    if (!holdKeyScroll && scrollx.tx <= scrollx.dx) {
      animationXFrame = $.requestAnimationFrame(scrollXFunction);
    } else {
      $.cancelAnimationFrame(animationXFrame);
      $scrollTo(scrollXElem, scrollx.x1, null);
      scrollx.x0 = scrollx.x1 = scrollx.xc = scrollx.tx = 0;
      if (scroll.callback)
        scroll.callback();
    }
  };

  $.setSmoothScrollEaseFN = function(fn) {
    easeFn = fn;
  };

  $.smoothScrollTo = function(elem, x, y, d, callback) {
    scrollElem = elem;
    $.cancelAnimationFrame(animationXFrame);
    $.cancelAnimationFrame(animationYFrame);
    scroll.dx = scroll.dy = d;
    scrollx.dx = scrollx.dy = d;
    scroll.callback = callback || function() {};
    if (x !== scrollElem.scrollLeft) {
      scrollXElem = elem;
      scrollx.x0 = scrollXElem.scrollLeft;
      scrollx.x1 = x;
      scrollx.tx = 0;
      scrollx.txo = timeFn();
      scrollXFunction();
    }
    if (y !== scrollElem.scrollTop) {
      scroll.y0 = scrollElem.scrollTop;
      scroll.y1 = y;
      scroll.ty = 0;
      scroll.tyo = timeFn();
      scrollYFunction();
    }
  };

  var holdFunction = function(dx, dy) {
    var se = dx ? scrollXElem : scrollElem;
    return (function animationLoop() {
      if ($.scrollKeyUp) {
        holdKeyScroll = false;
        return;
      }
      $scrollBy(se, dx, dy);
      $.requestAnimationFrame(animationLoop);
    })();
  };

  $.smoothScrollBy = function(elem, x, y, d, callback) {
    if (x) {
      scrollXElem = elem;
    } else {
      scrollElem = elem;
    }
    if (!$.scrollKeyUp && x === lastX && y === lastY) {
      if (!holdKeyScroll) {
        holdKeyScroll = true;
        holdFunction(x * 0.25, y * 0.25);
      }
      return;
    }
    scroll.callback = callback || function() {};
    lastX = x;
    lastY = y;
    $.scrollKeyUp = false;
    holdKeyScroll = false;
    if (x) {
      var oldDx = scrollx.x1 - scrollx.xc;
      $.cancelAnimationFrame(animationXFrame);
      scrollx.dx = d;
      scrollx.x0 = scrollXElem.scrollLeft;
      scrollx.x1 = oldDx + scrollx.x0 + x;
      scrollx.tx = 0;
      scrollx.txo = timeFn();
      scrollXFunction();
    }
    if (y) {
      var oldDy = scroll.y1 - scroll.yc;
      scroll.dy = d;
      scroll.y0 = scrollElem.scrollTop;
      scroll.y1 = oldDy + scroll.y0 + y;
      scroll.ty = 0;
      scroll.tyo = timeFn();
      $.cancelAnimationFrame(animationYFrame);
      scrollYFunction();
    }
  };

  $.scrollKeyUp = true;

})(this);

Scroll.historyStateEquals = function(s1, s2) {
  if (!s1 || !s2)
    return false;
  return s1[0] === s2[0] &&
    s1[1] === s2[1] &&
    s1[2] === s2[2];
};

Scroll.scrollToHistoryState = function(index) {
  index = index || this.historyIndex;
  var state = this.history[index];
  if (!state)
    return;
  var scrollElem = state[0];
  scrollElem.scrollLeft = state[1];
  scrollElem.scrollTop = state[2];
  this.historyIndex = index;
};

Scroll.previousHistoryState = function() {
  if (!this.historyStateEquals(this.lastState(), this.currentState()))
    this.addHistoryState();
  if (this.historyIndex > 0) {
    this.historyIndex--;
    this.scrollToHistoryState(this.historyIndex);
  }
};

Scroll.nextHistoryState = function() {
  if (this.historyIndex + 1 < this.history.length) {
    this.historyIndex++;
    this.scrollToHistoryState(this.historyIndex);
  }
};

Scroll.currentState = function() {
  // TODO make work with nested scrolling elements
  // var scrollElem = scrollingElement(SCROLLABLE);

  var scrollElem = document.scrollingElement;
  if (!scrollElem)
    return null;
  return [scrollElem, scrollElem.scrollLeft, scrollElem.scrollTop];
};

Scroll.lastState = function() {
  if (this.historyIndex >= this.history.length)
    return null;
  return this.history[this.historyIndex];
};

Scroll.addHistoryState = function() {
  var nextState = this.currentState();
  if (!nextState)
    return false;
  if (this.historyIndex + 1 < this.history.length)
    this.history = this.history.slice(0, this.historyIndex + 1);
  if (this.history.length) {
    if (this.historyStateEquals(this.lastState(), nextState))
      return false;
  }
  this.history.push(nextState);
  this.historyIndex = this.history.length - 1;
  return true;
};

Scroll.scroll = function(type, repeats) {

  var stepSize = settings ? settings.scrollstep : 60;

  var shouldLogPosition = !/^(up|down|left|right|pageUp|pageDown)$/.test(type);
  if (document.body && shouldLogPosition) {
    this.lastPosition = [document.scrollingElement.scrollLeft, document.scrollingElement.scrollTop];
    Scroll.addHistoryState();
  }

  var direction = (function() {
    switch (type) {
    case 'up': case 'pageUp': case 'fullPageUp': case 'top':
      return SCROLLABLE_Y_UP;
    case 'left': case 'leftmost':
      return SCROLLABLE_X_LEFT;
    case 'right': case 'rightmost':
      return SCROLLABLE_X_RIGHT;
    default:
      return SCROLLABLE_Y_DOWN;
    }
  })();

  var scrollElem = scrollingElement(direction),
      hy = scrollElem === document.body ? innerHeight : scrollElem.clientHeight,
      hw = scrollElem === document.body ? innerWidth  : scrollElem.clientWidth,
      x = 0,
      y = 0;

  switch (type) {
  case 'down':
    y = repeats * stepSize;
    break;
  case 'up':
    y -= repeats * stepSize;
    break;
  case 'pageDown':
    y = repeats * hy >> 1;
    break;
  case 'fullPageDown':
    y = repeats * hy * (settings.fullpagescrollpercent / 100 || 1);
    break;
  case 'pageUp':
    y -= repeats * hy >> 1;
    break;
  case 'fullPageUp':
    y -= repeats * hy * (settings.fullpagescrollpercent / 100 || 1);
    break;
  case 'top':
    y -= scrollElem.scrollTop;
    break;
  case 'bottom':
    y = scrollElem.scrollHeight - scrollElem.scrollTop - hy + 20;
    break;
  case 'left':
    x -= repeats * stepSize >> 1;
    break;
  case 'right':
    x = repeats * stepSize >> 1;
    break;
  case 'leftmost':
    x -= scrollElem.scrollLeft;
    break;
  case 'rightmost':
    x = scrollElem.scrollWidth - scrollElem.scrollLeft - hw + 20;
    break;
  }

  if (settings && settings.smoothscroll) {
    window.smoothScrollBy(scrollElem, x, y, settings.scrollduration);
  } else {
    $scrollBy(scrollElem, x, y);
  }
};
<commit_msg>Use event.target rather than event.srcElement<commit_after>var Scroll = {
  positions: {},
  history: [],
  historyIndex: 0,
};

const NON_SCROLLABLE     = 0,
      SCROLLABLE_Y_DOWN  = 1,
      SCROLLABLE_Y_UP    = 2,
      SCROLLABLE_X_RIGHT = 4,
      SCROLLABLE_X_LEFT  = 8,
      SCROLLABLE = SCROLLABLE_X_LEFT | SCROLLABLE_X_RIGHT |
                   SCROLLABLE_Y_UP | SCROLLABLE_Y_DOWN;
// const SCROLLABLE_Y = SCROLLABLE_Y_UP   | SCROLLABLE_Y_DOWN,
//       SCROLLABLE_X = SCROLLABLE_X_LEFT | SCROLLABLE_X_RIGHT;

var scrollingElement = (function() {
  function getScrollType(elem) {
    var cs = getComputedStyle(elem);
    var st = NON_SCROLLABLE;
    if (cs.overflow === 'hidden')
      return st;
    if (cs.overflowX !== 'hidden' &&
        elem.offsetHeight > elem.clientHeight &&
        elem.scrollWidth > elem.clientWidth) {
      if (elem.scrollLeft > 0)
        st |= SCROLLABLE_X_LEFT;
      if (elem.scrollLeft + elem.clientWidth < elem.scrollWidth)
        st |= SCROLLABLE_X_RIGHT;
    }
    if (cs.overflowY !== 'hidden' &&
        elem.offsetWidth > elem.clientWidth &&
        elem.scrollHeight > elem.clientHeight) {
      if (elem.scrollTop > 0)
        st |= SCROLLABLE_Y_UP;
      if (elem.scrollTop + elem.clientHeight < elem.scrollHeight)
        st |= SCROLLABLE_Y_DOWN;
    }
    return st;
  }

  var lastActiveElem = null,
      lastScrollElem = null,
      clickFocus = false;

  window.resetScrollFocus = function() {
    clickFocus = false;
  };

  document.addEventListener('mousedown', function(event) {
    if (!event.isTrusted)
      return true;
    clickFocus = true;
    lastActiveElem = event.target;
  });

  return function scrollingElement(dir) {
    var elem;
    if (clickFocus) {
      elem = lastActiveElem;
    } else {
      elem = lastActiveElem = document.activeElement;
    }
    if (elem === null)
      return null;
    return (function climb(elem) {
      if (elem === null)
        return lastScrollElem || document.scrollingElement;
      if (elem === document.scrollingElement)
        return elem;
      var st = getScrollType(elem);
      return st & dir ? elem : climb(elem.parentElement);
    })(elem);
  };
})();

function $scrollBy(elem, x, y) {
  elem.scrollLeft += x;
  elem.scrollTop += y;
}
function $scrollTo(elem, x, y) {
  if (x !== null)
    elem.scrollLeft = x;
  if (y !== null)
    elem.scrollTop = y;
}

(function($) {

  var animationYFrame, animationXFrame,
      scrollXFunction, scrollYFunction,
      scrollElem, scrollXElem,
      lastX, lastY;
  var holdKeyScroll = false;

  var easeFn = function(t, b, c, d) {
    return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
  };

  var timeFn = typeof window.performance === 'undefined' ?
    Date.now : performance.now.bind(performance);

  var scroll = {
    x0:   0, // starting x position
    x1:   0, // ending x position
    xc:   0, // delta-x during scroll
    tx:   0, // delta-t
    txo:  0, // last time measurement
    dx:   0, // x-duration
    y0:   0,
    y1:   0,
    yc:   0,
    ty:   0,
    tyo:  0,
    dy:   0,
    callback: null,
  };
  var scrollx = Object.clone(scroll);

  scrollYFunction = function() {
    var delta = easeFn(scroll.ty, scroll.y0, scroll.y1 - scroll.y0, scroll.dy);
    var time = timeFn();
    scroll.yc = delta;
    scroll.ty += time - scroll.tyo;
    scroll.tyo = time;
    $scrollTo(scrollElem, null, delta);
    if (!holdKeyScroll && scroll.ty <= scroll.dy) {
      animationYFrame = $.requestAnimationFrame(scrollYFunction);
    } else {
      $.cancelAnimationFrame(animationYFrame);
      animationYFrame = null;
      $scrollTo(scrollElem, null, scroll.y1);
      scroll.y0 = scroll.y1 = scroll.yc = scroll.ty = 0;
      if (scroll.callback)
        scroll.callback();
    }
  };

  scrollXFunction = function() {
    var delta = easeFn(scrollx.tx, scrollx.x0, scrollx.x1 - scrollx.x0, scrollx.dx);
    var time = timeFn();
    scrollx.xc = delta;
    scrollx.tx += time - scrollx.txo;
    scrollx.txo = time;
    $scrollTo(scrollXElem, delta, null);
    if (!holdKeyScroll && scrollx.tx <= scrollx.dx) {
      animationXFrame = $.requestAnimationFrame(scrollXFunction);
    } else {
      $.cancelAnimationFrame(animationXFrame);
      $scrollTo(scrollXElem, scrollx.x1, null);
      scrollx.x0 = scrollx.x1 = scrollx.xc = scrollx.tx = 0;
      if (scroll.callback)
        scroll.callback();
    }
  };

  $.setSmoothScrollEaseFN = function(fn) {
    easeFn = fn;
  };

  $.smoothScrollTo = function(elem, x, y, d, callback) {
    scrollElem = elem;
    $.cancelAnimationFrame(animationXFrame);
    $.cancelAnimationFrame(animationYFrame);
    scroll.dx = scroll.dy = d;
    scrollx.dx = scrollx.dy = d;
    scroll.callback = callback || function() {};
    if (x !== scrollElem.scrollLeft) {
      scrollXElem = elem;
      scrollx.x0 = scrollXElem.scrollLeft;
      scrollx.x1 = x;
      scrollx.tx = 0;
      scrollx.txo = timeFn();
      scrollXFunction();
    }
    if (y !== scrollElem.scrollTop) {
      scroll.y0 = scrollElem.scrollTop;
      scroll.y1 = y;
      scroll.ty = 0;
      scroll.tyo = timeFn();
      scrollYFunction();
    }
  };

  var holdFunction = function(dx, dy) {
    var se = dx ? scrollXElem : scrollElem;
    return (function animationLoop() {
      if ($.scrollKeyUp) {
        holdKeyScroll = false;
        return;
      }
      $scrollBy(se, dx, dy);
      $.requestAnimationFrame(animationLoop);
    })();
  };

  $.smoothScrollBy = function(elem, x, y, d, callback) {
    if (x) {
      scrollXElem = elem;
    } else {
      scrollElem = elem;
    }
    if (!$.scrollKeyUp && x === lastX && y === lastY) {
      if (!holdKeyScroll) {
        holdKeyScroll = true;
        holdFunction(x * 0.25, y * 0.25);
      }
      return;
    }
    scroll.callback = callback || function() {};
    lastX = x;
    lastY = y;
    $.scrollKeyUp = false;
    holdKeyScroll = false;
    if (x) {
      var oldDx = scrollx.x1 - scrollx.xc;
      $.cancelAnimationFrame(animationXFrame);
      scrollx.dx = d;
      scrollx.x0 = scrollXElem.scrollLeft;
      scrollx.x1 = oldDx + scrollx.x0 + x;
      scrollx.tx = 0;
      scrollx.txo = timeFn();
      scrollXFunction();
    }
    if (y) {
      var oldDy = scroll.y1 - scroll.yc;
      scroll.dy = d;
      scroll.y0 = scrollElem.scrollTop;
      scroll.y1 = oldDy + scroll.y0 + y;
      scroll.ty = 0;
      scroll.tyo = timeFn();
      $.cancelAnimationFrame(animationYFrame);
      scrollYFunction();
    }
  };

  $.scrollKeyUp = true;

})(this);

Scroll.historyStateEquals = function(s1, s2) {
  if (!s1 || !s2)
    return false;
  return s1[0] === s2[0] &&
    s1[1] === s2[1] &&
    s1[2] === s2[2];
};

Scroll.scrollToHistoryState = function(index) {
  index = index || this.historyIndex;
  var state = this.history[index];
  if (!state)
    return;
  var scrollElem = state[0];
  scrollElem.scrollLeft = state[1];
  scrollElem.scrollTop = state[2];
  this.historyIndex = index;
};

Scroll.previousHistoryState = function() {
  if (!this.historyStateEquals(this.lastState(), this.currentState()))
    this.addHistoryState();
  if (this.historyIndex > 0) {
    this.historyIndex--;
    this.scrollToHistoryState(this.historyIndex);
  }
};

Scroll.nextHistoryState = function() {
  if (this.historyIndex + 1 < this.history.length) {
    this.historyIndex++;
    this.scrollToHistoryState(this.historyIndex);
  }
};

Scroll.currentState = function() {
  // TODO make work with nested scrolling elements
  // var scrollElem = scrollingElement(SCROLLABLE);

  var scrollElem = document.scrollingElement;
  if (!scrollElem)
    return null;
  return [scrollElem, scrollElem.scrollLeft, scrollElem.scrollTop];
};

Scroll.lastState = function() {
  if (this.historyIndex >= this.history.length)
    return null;
  return this.history[this.historyIndex];
};

Scroll.addHistoryState = function() {
  var nextState = this.currentState();
  if (!nextState)
    return false;
  if (this.historyIndex + 1 < this.history.length)
    this.history = this.history.slice(0, this.historyIndex + 1);
  if (this.history.length) {
    if (this.historyStateEquals(this.lastState(), nextState))
      return false;
  }
  this.history.push(nextState);
  this.historyIndex = this.history.length - 1;
  return true;
};

Scroll.scroll = function(type, repeats) {

  var stepSize = settings ? settings.scrollstep : 60;

  var shouldLogPosition = !/^(up|down|left|right|pageUp|pageDown)$/.test(type);
  if (document.body && shouldLogPosition) {
    this.lastPosition = [document.scrollingElement.scrollLeft, document.scrollingElement.scrollTop];
    Scroll.addHistoryState();
  }

  var direction = (function() {
    switch (type) {
    case 'up': case 'pageUp': case 'fullPageUp': case 'top':
      return SCROLLABLE_Y_UP;
    case 'left': case 'leftmost':
      return SCROLLABLE_X_LEFT;
    case 'right': case 'rightmost':
      return SCROLLABLE_X_RIGHT;
    default:
      return SCROLLABLE_Y_DOWN;
    }
  })();

  var scrollElem = scrollingElement(direction),
      hy = scrollElem === document.body ? innerHeight : scrollElem.clientHeight,
      hw = scrollElem === document.body ? innerWidth  : scrollElem.clientWidth,
      x = 0,
      y = 0;

  switch (type) {
  case 'down':
    y = repeats * stepSize;
    break;
  case 'up':
    y -= repeats * stepSize;
    break;
  case 'pageDown':
    y = repeats * hy >> 1;
    break;
  case 'fullPageDown':
    y = repeats * hy * (settings.fullpagescrollpercent / 100 || 1);
    break;
  case 'pageUp':
    y -= repeats * hy >> 1;
    break;
  case 'fullPageUp':
    y -= repeats * hy * (settings.fullpagescrollpercent / 100 || 1);
    break;
  case 'top':
    y -= scrollElem.scrollTop;
    break;
  case 'bottom':
    y = scrollElem.scrollHeight - scrollElem.scrollTop - hy + 20;
    break;
  case 'left':
    x -= repeats * stepSize >> 1;
    break;
  case 'right':
    x = repeats * stepSize >> 1;
    break;
  case 'leftmost':
    x -= scrollElem.scrollLeft;
    break;
  case 'rightmost':
    x = scrollElem.scrollWidth - scrollElem.scrollLeft - hw + 20;
    break;
  }

  if (settings && settings.smoothscroll) {
    window.smoothScrollBy(scrollElem, x, y, settings.scrollduration);
  } else {
    $scrollBy(scrollElem, x, y);
  }
};
<|endoftext|>


<commit_before>angular.module('foundation.actionsheet', ['foundation.common.services']);

angular.module('foundation.actionsheet')
  .controller('ZfActionSheetController', ['$scope', 'FoundationApi', function($scope, foundationApi) {
    var controller = this;
    var content = controller.content = $scope.content;

    controller.registerContent = function(scope) {
      content = scope;
      content.active = false;
    };

    controller.toggle = function() {
      content.toggle();
      content.$apply();
    };

    controller.hide = function() {
      content.hide();
      content.$apply();
    }

}]);

angular.module('foundation.actionsheet')
  .directive('zfActionSheet', ['FoundationApi', function(foundationApi) {
  return {
    restrict: 'A',
    transclude: true,
    replace: true,
    templateUrl: 'partials/actionsheet.html',
    controller: 'ZfActionSheetController',
    compile: function compile() {

      return {
        pre: function preLink(scope, iElement, iAttrs) {
          iAttrs.$set('zf-closable', 'actionsheet');
        },
        post: function postLink(scope, element, attrs, controller) {
          foundationApi.subscribe(attrs.id, function(msg) {
            if (msg == 'toggle') {
              controller.toggle();
            }

            if (msg === 'hide' || msg === 'close') {
              controller.hide();
            }

            return;
          });

        }
      }
    }
  };
}]);

angular.module('foundation.actionsheet')
  .directive('zfAsContent', ['FoundationApi', function(foundationApi) {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    templateUrl: 'partials/actionsheet-content.html',
    require: '^zfActionSheet',
    scope: {
      position: '@?'
    },
    link: function(scope, element, attrs, controller) {
      scope.active = false;
      scope.position = scope.position || 'bottom';
      controller.registerContent(scope);

      scope.toggle = function() {
        scope.active = !scope.active;
        return;
      };

      scope.hide = function() {
        scope.active = false;
        return;
      }
    },
  };
}]);

angular.module('foundation.actionsheet')
  .directive('zfAsButton', ['FoundationApi', function(foundationApi) {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    templateUrl: 'partials/actionsheet-button.html',
    require: '^zfActionSheet',
    scope: {
      title: '@?'
    },
    link: function(scope, element, attrs, controller) {

      element.on('click', function(e) {
        controller.toggle();
        e.preventDefault();
      });

    },
  };
}]);
<commit_msg>Add element type to actionsheet directive<commit_after>angular.module('foundation.actionsheet', ['foundation.common.services']);

angular.module('foundation.actionsheet')
  .controller('ZfActionSheetController', ['$scope', 'FoundationApi', function($scope, foundationApi) {
    var controller = this;
    var content = controller.content = $scope.content;

    controller.registerContent = function(scope) {
      content = scope;
      content.active = false;
    };

    controller.toggle = function() {
      content.toggle();
      content.$apply();
    };

    controller.hide = function() {
      content.hide();
      content.$apply();
    }

}]);

angular.module('foundation.actionsheet')
  .directive('zfActionSheet', ['FoundationApi', function(foundationApi) {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    templateUrl: 'partials/actionsheet.html',
    controller: 'ZfActionSheetController',
    compile: function compile() {

      return {
        pre: function preLink(scope, iElement, iAttrs) {
          iAttrs.$set('zf-closable', 'actionsheet');
        },
        post: function postLink(scope, element, attrs, controller) {
          foundationApi.subscribe(attrs.id, function(msg) {
            if (msg == 'toggle') {
              controller.toggle();
            }

            if (msg === 'hide' || msg === 'close') {
              controller.hide();
            }

            return;
          });

        }
      }
    }
  };
}]);

angular.module('foundation.actionsheet')
  .directive('zfAsContent', ['FoundationApi', function(foundationApi) {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    templateUrl: 'partials/actionsheet-content.html',
    require: '^zfActionSheet',
    scope: {
      position: '@?'
    },
    link: function(scope, element, attrs, controller) {
      scope.active = false;
      scope.position = scope.position || 'bottom';
      controller.registerContent(scope);

      scope.toggle = function() {
        scope.active = !scope.active;
        return;
      };

      scope.hide = function() {
        scope.active = false;
        return;
      }
    },
  };
}]);

angular.module('foundation.actionsheet')
  .directive('zfAsButton', ['FoundationApi', function(foundationApi) {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    templateUrl: 'partials/actionsheet-button.html',
    require: '^zfActionSheet',
    scope: {
      title: '@?'
    },
    link: function(scope, element, attrs, controller) {

      element.on('click', function(e) {
        controller.toggle();
        e.preventDefault();
      });

    },
  };
}]);
<|endoftext|>


<commit_before><commit_msg>Logic to hide/show banners<commit_after><|endoftext|>


<commit_before>// @flow

import * as ls from './languageclient';
import * as rpc from 'vscode-jsonrpc';

import {ConsoleLogger, NullLogger, type Logger} from './logger';

import AutocompleteAdapter from './adapters/autocomplete-adapter';
import DocumentSyncAdapter from './adapters/document-sync-adapter';
import FormatCodeAdapter from './adapters/format-code-adapter';
import LinterAdapter from './adapters/linter-adapter';
import NotificationsAdapter from './adapters/notifications-adapter';
import NuclideDefinitionAdapter from './adapters/nuclide-definition-adapter';
import NuclideFindReferencesAdapter from './adapters/nuclide-find-references-adapter';
import NuclideHyperclickAdapter from './adapters/nuclide-hyperclick-adapter';
import NuclideOutlineViewAdapter from './adapters/nuclide-outline-view-adapter';

import {CompositeDisposable} from 'atom';

export default class AutoLanguageClient {
  _disposable = new CompositeDisposable();
  _process: ?child_process$ChildProcess;
  _lc: ls.LanguageClientConnection;

  autoComplete: ?AutocompleteAdapter;
  linter: ?LinterAdapter;

  definitions: ?NuclideDefinitionAdapter;
  findReferences: ?NuclideFindReferencesAdapter;
  hyperclick: ?NuclideHyperclickAdapter;
  outlineView: ?NuclideOutlineViewAdapter;

  logger: Logger;
  name: string;

  getGrammarScopes(): Array<string> {
    throw Error('Must implement getGrammarScopes when extending AutoLanguageClient');
  }
  getLanguageName(): string {
    throw Error('Must implement getLanguageName when extending AutoLanguageClient');
  }
  getServerName(): string {
    throw Error('Must implement getServerName when extending AutoLanguageClient');
  }

  activate(): void {
    this.name = `${this.getLanguageName()} (${this.getServerName()})`;
    this.logger = atom.config.get('core.debugLSP') ? new ConsoleLogger(this.name) : new NullLogger();
    this.startServer();
  }

  deactivate(): void {
    this._disposable.dispose();

    if (this._lc) {
      this._lc.shutdown();
    }

    if (this._process != null) {
      this._process.kill();
      this._process = null;
    }
  }

  async startServer(): Promise<void> {
    if (this._process != null) {
      return;
    }

    this._process = await this.startServerProcess();
    this._lc = new ls.LanguageClientConnection(this.createServerConnection(), this.logger);
    this.preInitialization();

    const initializeResponse = await this._lc.initialize(this.getInitializeParams());
    this.adaptCapabilities(initializeResponse.capabilities);
    this.postInitialization(initializeResponse);
  }

  startServerProcess(): child_process$ChildProcess {
    throw Error('Must override startServerProcess to start language server process when extending AutoLanguageClient');
  }

  createServerConnection(): rpc.Connection {
    if (this._process == null) {
      throw Error('Process must be set before creating RPC connection to server process');
    }

    return rpc.createMessageConnection(
      new rpc.StreamMessageReader(this._process.stdout),
      new rpc.StreamMessageWriter(this._process.stdin),
      {error: m => { this.logger.error(m); }});
  }

  getProjectRoot(): ?string {
    const rootDirs: Array<atom$Directory> = atom.project.getDirectories();
    return rootDirs.length > 0 ? rootDirs[0].path : null
  }

  getInitializeParams(): ls.InitializeParams {
    return {
      processId: process.pid,
      capabilities: { },
      rootPath: this.getProjectRoot(),
    };
  }

  adaptCapabilities(capabilities: ls.ServerCapabilities): void {
    this.linter = new LinterAdapter(this._lc);
    if (capabilities.completionProvider) {
      this.autoComplete = new AutocompleteAdapter();
    }

    this.adaptToNuclide(capabilities);

    new NotificationsAdapter(this._lc, this.name);

    if (capabilities.textDocumentSync) {
      this._disposable.add(new DocumentSyncAdapter(this._lc, capabilities.textDocumentSync));
    }
    if (capabilities.documentRangeFormattingProvider || capabilities.documentFormattingProvider) {
      this._disposable.add(new FormatCodeAdapter(this._lc, capabilities, this.getGrammarScopes()));
    }
  }

  adaptToNuclide(capabilities: ls.ServerCapabilities): void {
    if (capabilities.definitionProvider) {
      this.definitions = new NuclideDefinitionAdapter(this.getLanguageName());
      this.hyperclick = new NuclideHyperclickAdapter();
    }
    if (capabilities.documentSymbolProvider) {
      this.outlineView = new NuclideOutlineViewAdapter();
    }
    if (capabilities.referencesProvider) {
      this.findReferences = new NuclideFindReferencesAdapter();
    }
  }

  preInitialization(): void {
  }

  postInitialization(InitializationResult: ls.InitializeResult): void {
  }

  // Atom Autocomplete+ via LS completion

  provideAutocomplete(): atom$AutocompleteProvider {
    return {
      selector: '.source',
      excludeLowerPriority: false,
      getSuggestions: this.getSuggestions.bind(this),
    };
  }

  getSuggestions(request: any): Promise<Array<atom$AutocompleteSuggestion>> {
    return this.autoComplete != null ? this.autoComplete.getSuggestions(this._lc, request) : Promise.resolve([]);
  }

  // Nuclide Definitions via LS documentHighlight and gotoDefinition

  provideDefinitions(): nuclide$DefinitionProvider {
    return {
      name: this.name,
      priority: 20,
      grammarScopes: this.getGrammarScopes(),
      getDefinition: this.getDefinition.bind(this),
      getDefinitionById: this.getDefinitionById.bind(this),
    };
  }

  getDefinition(editor: TextEditor, point: atom$Point): Promise<?nuclide$DefinitionQueryResult> {
    return this.definitions != null ? this.definitions.getDefinition(this._lc, editor, point) : Promise.resolve(null);
  }

  getDefinitionById(filename: NuclideUri, id: string): Promise<?nuclide$Definition> {
    return Promise.resolve(null); // TODO: Is this needed?
  }

  // Nuclide Outline View via LS documentSymbol

  provideOutlines(): nuclide$OutlineProvider {
    return {
      name: this.name,
      grammarScopes: this.getGrammarScopes(),
      priority: 1,
      getOutline: this.getOutline.bind(this),
    };
  }

  getOutline(editor: atom$TextEditor): Promise<?nuclide$Outline> {
    return this.outlineView != null ? this.outlineView.getOutline(this._lc, editor) : Promise.resolve(null);
  }

  // Linter API via LS publishDiagnostics

  provideLinter(): linter$StandardLinter {
    return {
      name: this.name,
      grammarScopes: this.getGrammarScopes(),
      scope: 'project',
      lintOnFly: true,
      lint: this.getLinting.bind(this),
    };
  }

  getLinting(editor: atom$TextEditor): ?Array<linter$Message> | Promise<?Array<linter$Message>> {
    return this.linter != null ? this.linter.provideDiagnostics() : Promise.resolve([]);
  }

  // Nuclide Find References via LS findReferences

  provideFindReferences(): nuclide$FindReferencesProvider {
    return {
      isEditorSupported: (editor: atom$TextEditor) => this.getGrammarScopes().includes(editor.getGrammar().scopeName),
      findReferences: this.getReferences.bind(this),
    };
  }

  getReferences(editor: atom$TextEditor, point: atom$Point): Promise<?nuclide$FindReferencesReturn> {
    return this.findReferences != null
      ? this.findReferences.getReferences(this._lc, editor, point, this.getProjectRoot())
      : Promise.resolve(null);
  }

  // Nuclide Hyperlick via LS gotoDefinition and documentHighlight

  provideHyperclick(): nuclide$HyperclickProvider {
    return {
      priority: 20,
      providerName: this.name,
      getSuggestion: this.getHyperclickSuggestion.bind(this),
    };
  }

  getHyperclickSuggestion(editor: atom$TextEditor, point: atom$Point): Promise<?nuclide$HyperclickSuggestion> {
    return this.hyperclick != null ? this.hyperclick.getSuggestion(this._lc, editor, point) : Promise.resolve(null);
  }
}
<commit_msg>Lazy instantiate adapters where possible<commit_after>// @flow

import * as ls from './languageclient';
import * as rpc from 'vscode-jsonrpc';

import {ConsoleLogger, NullLogger, type Logger} from './logger';

import AutocompleteAdapter from './adapters/autocomplete-adapter';
import DocumentSyncAdapter from './adapters/document-sync-adapter';
import FormatCodeAdapter from './adapters/format-code-adapter';
import LinterAdapter from './adapters/linter-adapter';
import NotificationsAdapter from './adapters/notifications-adapter';
import NuclideDefinitionAdapter from './adapters/nuclide-definition-adapter';
import NuclideFindReferencesAdapter from './adapters/nuclide-find-references-adapter';
import NuclideHyperclickAdapter from './adapters/nuclide-hyperclick-adapter';
import NuclideOutlineViewAdapter from './adapters/nuclide-outline-view-adapter';

import {CompositeDisposable} from 'atom';

export default class AutoLanguageClient {
  _disposable = new CompositeDisposable();
  _process: ?child_process$ChildProcess;
  _lc: ls.LanguageClientConnection;

  autoComplete: ?AutocompleteAdapter;
  linter: ?LinterAdapter;
  definitions: ?NuclideDefinitionAdapter;
  findReferences: ?NuclideFindReferencesAdapter;
  hyperclick: ?NuclideHyperclickAdapter;
  outlineView: ?NuclideOutlineViewAdapter;

  serverCapabilities: ls.ServerCapabilities;

  logger: Logger;
  name: string;

  getGrammarScopes(): Array<string> {
    throw Error('Must implement getGrammarScopes when extending AutoLanguageClient');
  }
  getLanguageName(): string {
    throw Error('Must implement getLanguageName when extending AutoLanguageClient');
  }
  getServerName(): string {
    throw Error('Must implement getServerName when extending AutoLanguageClient');
  }

  activate(): void {
    this.name = `${this.getLanguageName()} (${this.getServerName()})`;
    this.logger = atom.config.get('core.debugLSP') ? new ConsoleLogger(this.name) : new NullLogger();
    this.startServer();
  }

  deactivate(): void {
    this._disposable.dispose();

    if (this._lc) {
      this._lc.shutdown();
    }

    if (this._process != null) {
      this._process.kill();
      this._process = null;
    }
  }

  async startServer(): Promise<void> {
    if (this._process != null) {
      return;
    }

    this._process = await this.startServerProcess();
    this._lc = new ls.LanguageClientConnection(this.createServerConnection(), this.logger);
    this.preInitialization();

    const initializeResponse = await this._lc.initialize(this.getInitializeParams());
    this.serverCapabilities = initializeResponse.capabilities;
    this.postInitialization(initializeResponse);
  }

  startServerProcess(): child_process$ChildProcess {
    throw Error('Must override startServerProcess to start language server process when extending AutoLanguageClient');
  }

  createServerConnection(): rpc.Connection {
    if (this._process == null) {
      throw Error('Process must be set before creating RPC connection to server process');
    }

    return rpc.createMessageConnection(
      new rpc.StreamMessageReader(this._process.stdout),
      new rpc.StreamMessageWriter(this._process.stdin),
      {error: m => { this.logger.error(m); }});
  }

  getProjectRoot(): ?string {
    const rootDirs: Array<atom$Directory> = atom.project.getDirectories();
    return rootDirs.length > 0 ? rootDirs[0].path : null
  }

  getInitializeParams(): ls.InitializeParams {
    return {
      processId: process.pid,
      capabilities: { },
      rootPath: this.getProjectRoot(),
    };
  }

  adaptCapabilities(capabilities: ls.ServerCapabilities): void {
    new NotificationsAdapter(this._lc, this.name);

    if (capabilities.textDocumentSync) {
      this._disposable.add(new DocumentSyncAdapter(this._lc, capabilities.textDocumentSync));
    }
    if (capabilities.documentRangeFormattingProvider || capabilities.documentFormattingProvider) {
      this._disposable.add(new FormatCodeAdapter(this._lc, capabilities, this.getGrammarScopes()));
    }
  }

  preInitialization(): void {
  }

  postInitialization(InitializationResult: ls.InitializeResult): void {
  }

  // Atom Autocomplete+ via LS completion

  provideAutocomplete(): atom$AutocompleteProvider {
    return {
      selector: '.source',
      excludeLowerPriority: false,
      getSuggestions: this.getSuggestions.bind(this),
    };
  }

  getSuggestions(request: any): Promise<Array<atom$AutocompleteSuggestion>> {
    if (this.autoComplete == null) {
      if (this.serverCapabilities.completionProvider) {
        this.autoComplete = new AutocompleteAdapter();
      } else {
        return Promise.resolve([]);
      }
    }

    return this.autoComplete.getSuggestions(this._lc, request);
  }

  // Nuclide Definitions via LS documentHighlight and gotoDefinition

  provideDefinitions(): nuclide$DefinitionProvider {
    return {
      name: this.name,
      priority: 20,
      grammarScopes: this.getGrammarScopes(),
      getDefinition: this.getDefinition.bind(this),
      getDefinitionById: this.getDefinitionById.bind(this),
    };
  }

  getDefinition(editor: TextEditor, point: atom$Point): Promise<?nuclide$DefinitionQueryResult> {
    if (this.definitions == null) {
      if (this.serverCapabilities.definitionProvider) {
        this.definitions = new NuclideDefinitionAdapter(this.getLanguageName());
      } else {
        return Promise.resolve(null);
      }
    }

    return this.definitions.getDefinition(this._lc, editor, point);
  }

  getDefinitionById(filename: NuclideUri, id: string): Promise<?nuclide$Definition> {
    return Promise.resolve(null); // TODO: Is this needed?
  }

  // Nuclide Outline View via LS documentSymbol

  provideOutlines(): nuclide$OutlineProvider {
    return {
      name: this.name,
      grammarScopes: this.getGrammarScopes(),
      priority: 1,
      getOutline: this.getOutline.bind(this),
    };
  }

  getOutline(editor: atom$TextEditor): Promise<?nuclide$Outline> {
    if (this.outlineView == null) {
      if (this.serverCapabilities.documentSymbolProvider) {
        this.outlineView = new NuclideOutlineViewAdapter();
      } else {
        return Promise.resolve(null);
      }
    }

    return this.outlineView.getOutline(this._lc, editor);
  }

  // Linter API via LS publishDiagnostics

  provideLinter(): linter$StandardLinter {
    return {
      name: this.name,
      grammarScopes: this.getGrammarScopes(),
      scope: 'project',
      lintOnFly: true,
      lint: this.getLinting.bind(this),
    };
  }

  getLinting(editor: atom$TextEditor): ?Array<linter$Message> | Promise<?Array<linter$Message>> {
    if (this.linter == null) {
      this.linter = new LinterAdapter(this._lc);
    }

    return this.linter.provideDiagnostics();
  }

  // Nuclide Find References via LS findReferences

  provideFindReferences(): nuclide$FindReferencesProvider {
    return {
      isEditorSupported: (editor: atom$TextEditor) => this.getGrammarScopes().includes(editor.getGrammar().scopeName),
      findReferences: this.getReferences.bind(this),
    };
  }

  getReferences(editor: atom$TextEditor, point: atom$Point): Promise<?nuclide$FindReferencesReturn> {
    if (this.findReferences == null) {
      if (this.serverCapabilities.referencesProvider) {
        this.findReferences = new NuclideFindReferencesAdapter();
      } else {
        return Promise.resolve(null);
      }
    }

    return this.findReferences.getReferences(this._lc, editor, point, this.getProjectRoot());
  }

  // Nuclide Hyperlick via LS gotoDefinition and documentHighlight

  provideHyperclick(): nuclide$HyperclickProvider {
    return {
      priority: 20,
      providerName: this.name,
      getSuggestion: this.getHyperclickSuggestion.bind(this),
    };
  }

  getHyperclickSuggestion(editor: atom$TextEditor, point: atom$Point): Promise<?nuclide$HyperclickSuggestion> {
    if (this.hyperclick == null) {
      if (this.serverCapabilities.definitionProvider) {
        this.hyperclick = new NuclideHyperclickAdapter();
      } else {
        return Promise.resolve(null);
      }
    }

    return this.hyperclick.getSuggestion(this._lc, editor, point);
  }
}
<|endoftext|>