<commit_before>var nodeUrl = require('url');
var request = require('request');
var serverSecrets;
try {
  // Everything that cannot be checked in but is useful server-side
  // is stored in this JSON data.
  serverSecrets = require('./secret.json');
} catch(e) { console.error('No secret data (secret.json, see server.js):', e); }

// data: {url}, JSON-serializable object.
// end: function(json), with json of the form:
//  - badges: list of objects of the form:
//    - link: target as a string URL.
//    - badge: shields image URL.
//    - name: string
var suggest = function(data, end, ask) {
  ask.res.setHeader('Access-Control-Allow-Origin', 'http://shields.io');
  try {
    var url = nodeUrl.parse(data.url);
  } catch(e) { end({err:''+e}); return; }
  findSuggestions(url, end);
};

// url: string
// cb: function({badges})
var findSuggestions = function(url, cb) {
  var userRepo = url.pathname.slice(1).split('/');
  var user = userRepo[0];
  var repo = userRepo[1];
  var promises = [];
  if (url.hostname === 'github.com') {
    promises = promises.concat([
      githubIssues(user, repo),
      githubForks(user, repo),
      githubStars(user, repo),
      githubLicense(user, repo),
    ]);
  }
  promises.push(twitterPage(url));
  Promise.all(promises).then(function(badges) {
    cb({badges:badges.filter(function(b) { return b != null; })});
  }).catch(function(err) {
    cb({badges:[], err:err});
  });
};

var twitterPage = function(url) {
  var schema = url.protocol.slice(0, -1);
  var host = url.host;
  var path = url.path;
  return Promise.resolve({
    name: 'Twitter',
    link: 'https://twitter.com/intent/tweet?text=Wow:&url=' + encodeURIComponent(url),
    badge: 'https://img.shields.io/twitter/url/' + schema + '/' + host + path + '.svg?style=social',
  });
};
var githubIssues = function(user, repo) {
  var userRepo = user + '/' + repo;
  return Promise.resolve({
    name: 'GitHub issues',
    link: 'https://github.com/' + userRepo + '/issues',
    badge: 'https://img.shields.io/github/issues/' + userRepo + '.svg',
  });
};
var githubForks = function(user, repo) {
  var userRepo = user + '/' + repo;
  return Promise.resolve({
    name: 'GitHub forks',
    link: 'https://github.com/' + userRepo + '/network',
    badge: 'https://img.shields.io/github/forks/' + userRepo + '.svg',
  });
};
var githubStars = function(user, repo) {
  var userRepo = user + '/' + repo;
  return Promise.resolve({
    name: 'GitHub stars',
    link: 'https://github.com/' + userRepo + '/stargazers',
    badge: 'https://img.shields.io/github/stars/' + userRepo + '.svg',
  });
};

// user: eg, qubyte
// repo: eg, rubidium
// returns a promise of {link, badge, name}
var githubLicense = function(user, repo) {
  return new Promise(function(resolve, reject) {
    // Step 1: Get the repo's default branch.
    var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '';
    // Using our OAuth App secret grants us 5000 req/hour
    // instead of the standard 60 req/hour.
    if (serverSecrets) {
      apiUrl += '?client_id=' + serverSecrets.gh_client_id
        + '&client_secret=' + serverSecrets.gh_client_secret;
    }
    var badgeData = {text:['license',''], colorscheme:'blue'};
    // A special User-Agent is required:
    // http://developer.github.com/v3/#user-agent-required
    request(apiUrl, { headers: { 'User-Agent': 'Shields.io' } }, function(err, res, buffer) {
      if (err != null) { resolve(null); return; }
      try {
        if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
        var data = JSON.parse(buffer);
        var defaultBranch = data.default_branch;
        // Step 2: Get the SHA-1 hash of the branch tip.
        var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '/branches/' + defaultBranch;
        if (serverSecrets) {
          apiUrl += '?client_id=' + serverSecrets.gh_client_id
            + '&client_secret=' + serverSecrets.gh_client_secret;
        }
        request(apiUrl, { headers: { 'User-Agent': 'Shields.io' } }, function(err, res, buffer) {
          if (err != null) { resolve(null); return; }
          try {
            if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
            var data = JSON.parse(buffer);
            var branchTip = data.commit.sha;
            // Step 3: Get the tree at the commit.
            var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '/git/trees/' + branchTip;
            if (serverSecrets) {
              apiUrl += '?client_id=' + serverSecrets.gh_client_id
                + '&client_secret=' + serverSecrets.gh_client_secret;
            }
            request(apiUrl, { headers: { 'User-Agent': 'Shields.io' } }, function(err, res, buffer) {
              if (err != null) { resolve(null); return; }
              try {
                if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
                var data = JSON.parse(buffer);
                var treeArray = data.tree;
                var licenseBlob;
                var licenseFilename;
                // Crawl each file in the root directory
                for (var i = 0; i < treeArray.length; i++) {
                  if (treeArray[i].type != 'blob') {
                    continue;
                  }
                  if (treeArray[i].path.match(/(LICENSE|COPYING|COPYRIGHT).*/i)) {
                    licenseBlob = treeArray[i].sha;
                    licenseFilename = treeArray[i].path;
                    break;
                  }
                }
                // Could not find license file
                if (!licenseBlob) { resolve(null); return; }

                // Step 4: Get the license blob.
                var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '/git/blobs/' + licenseBlob;
                var link = 'https://raw.githubusercontent.com/' +
                  [user, repo, defaultBranch, licenseFilename].join('/');

                if (serverSecrets) {
                  apiUrl += '?client_id=' + serverSecrets.gh_client_id
                    + '&client_secret=' + serverSecrets.gh_client_secret;
                }
                // Get the raw blob instead of JSON
                // https://developer.github.com/v3/media/
                request(apiUrl, { headers: { 'User-Agent': 'Shields.io', 'Accept': 'appplication/vnd.github.raw' } },
                function(err, res, buffer) {
                  if (err != null) { resolve(null); return; }
                  try {
                    if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
                    var license = guessLicense(buffer);
                    if (license) {
                      badgeData.text[1] = license;
                      resolve({
                        link: link,
                        badge: shieldsBadge(badgeData),
                        name: 'GitHub license'
                      });
                      return;
                    } else {
                      // Not a recognized license
                      resolve(null);
                      return;
                    }
                  } catch(e) { reject(e); return; }
                });
              } catch(e) { reject(e); return; }
            });
          } catch(e) { reject(e); return; }
        });
      } catch(e) { reject(e); return; }
    });
  });
};

// Key phrases for common licenses
var licensePhrases = {
  'Apache 1.1': 'apache (software )?license,? (version)? 1\\.1',
  'Apache 2': 'apache (software )?license,? (version)? 2',
  'Original BSD': 'all advertising materials mentioning features or use of this software must display the following acknowledgement',
  'New BSD': 'may be used to endorse or promote products derived from this software without specific prior written permission',
  'BSD': 'redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met',
  'AGPLv1': 'affero general public license,? version 1',
  'AGPLv3': 'affero general public license,? version 3',
  'AGPL': 'affero general public license',
  'GPLv2': 'gnu general public license,? version 2',
  'GPLv3': 'gnu general public license,? version 3',
  'GPL': 'gnu general public license',
  'LGPLv2.0': 'gnu library general public license,? version 2',
  'LGPLv2.1': 'gnu lesser general public license,? version 2\\.1',
  'LGPLv3': 'gnu lesser general public license,? version 3',
  'LGPL': 'gnu (library|lesser) general public license',
  'MIT': '\\(?(mit|expat|x11)\\)? license|permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files',
  'MPL 1.1': 'mozilla public license,? (\\(MPL\\) )?(version |v|v\\.)?1\\.1',
  'MPL 2': 'mozilla public license,? (\\(MPL\\) )?(version |v|v\\.)?2',
  'MPL': 'mozilla public license',
  'CDDL': 'common development and distribution license',
  'Eclipse': 'eclipse public license',
  'Artistic': 'artistic license',
  'zlib': 'the origin of this software must not be misrepresented',
  'ISC': 'permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted',
  'CC0': 'cc0',
  'Unlicense': 'this is free and unencumbered software released into the public domain',
}
var licenseCodes = Object.keys(licensePhrases);
var spaceMetaRegex = new RegExp(' ', 'g');

// Spaces can be any whitespace
for (var i = 0; i < licenseCodes.length; i++) {
  licensePhrases[licenseCodes[i]] = licensePhrases[licenseCodes[i]].replace(spaceMetaRegex, '\\s+');
}

// Try to guess the license based on the text and return an abbreviated name (or null if not recognized).
var guessLicense = function(text) {
  var licenseRegex;
  for (var i = 0; i < licenseCodes.length; i++) {
    licenseRegex = licensePhrases[licenseCodes[i]];
    if (text.match(new RegExp(licenseRegex, 'i'))) {
      return licenseCodes[i];
    }
  }
  // Not a recognized license
  return null;
};

var shieldsBadge = function(badgeData) {
  return ('https://img.shields.io/badge/'
    + escapeField(badgeData.text[0])
    + '-' + escapeField(badgeData.text[1])
    + '-' + badgeData.colorscheme + '.svg');
};

var escapeField = function(s) {
  return encodeURIComponent(s.replace(/-/g, '--').replace(/_/g, '__'));
};

module.exports = suggest;
<commit_msg>Allow CORS for suggestions on https://shields.io<commit_after>var nodeUrl = require('url');
var request = require('request');
var serverSecrets;
try {
  // Everything that cannot be checked in but is useful server-side
  // is stored in this JSON data.
  serverSecrets = require('./secret.json');
} catch(e) { console.error('No secret data (secret.json, see server.js):', e); }

// data: {url}, JSON-serializable object.
// end: function(json), with json of the form:
//  - badges: list of objects of the form:
//    - link: target as a string URL.
//    - badge: shields image URL.
//    - name: string
var suggest = function(data, end, ask) {
  var origin = ask.req.headers['origin'];
  if (/^https?:\/\/shields\.io$/.test(origin)) {
    ask.res.setHeader('Access-Control-Allow-Origin', origin);
  } else {
    ask.res.setHeader('Access-Control-Allow-Origin', 'null');
    end({err:'Disallowed'});
    return;
  }
  try {
    var url = nodeUrl.parse(data.url);
  } catch(e) { end({err:''+e}); return; }
  findSuggestions(url, end);
};

// url: string
// cb: function({badges})
var findSuggestions = function(url, cb) {
  var userRepo = url.pathname.slice(1).split('/');
  var user = userRepo[0];
  var repo = userRepo[1];
  var promises = [];
  if (url.hostname === 'github.com') {
    promises = promises.concat([
      githubIssues(user, repo),
      githubForks(user, repo),
      githubStars(user, repo),
      githubLicense(user, repo),
    ]);
  }
  promises.push(twitterPage(url));
  Promise.all(promises).then(function(badges) {
    cb({badges:badges.filter(function(b) { return b != null; })});
  }).catch(function(err) {
    cb({badges:[], err:err});
  });
};

var twitterPage = function(url) {
  var schema = url.protocol.slice(0, -1);
  var host = url.host;
  var path = url.path;
  return Promise.resolve({
    name: 'Twitter',
    link: 'https://twitter.com/intent/tweet?text=Wow:&url=' + encodeURIComponent(url),
    badge: 'https://img.shields.io/twitter/url/' + schema + '/' + host + path + '.svg?style=social',
  });
};
var githubIssues = function(user, repo) {
  var userRepo = user + '/' + repo;
  return Promise.resolve({
    name: 'GitHub issues',
    link: 'https://github.com/' + userRepo + '/issues',
    badge: 'https://img.shields.io/github/issues/' + userRepo + '.svg',
  });
};
var githubForks = function(user, repo) {
  var userRepo = user + '/' + repo;
  return Promise.resolve({
    name: 'GitHub forks',
    link: 'https://github.com/' + userRepo + '/network',
    badge: 'https://img.shields.io/github/forks/' + userRepo + '.svg',
  });
};
var githubStars = function(user, repo) {
  var userRepo = user + '/' + repo;
  return Promise.resolve({
    name: 'GitHub stars',
    link: 'https://github.com/' + userRepo + '/stargazers',
    badge: 'https://img.shields.io/github/stars/' + userRepo + '.svg',
  });
};

// user: eg, qubyte
// repo: eg, rubidium
// returns a promise of {link, badge, name}
var githubLicense = function(user, repo) {
  return new Promise(function(resolve, reject) {
    // Step 1: Get the repo's default branch.
    var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '';
    // Using our OAuth App secret grants us 5000 req/hour
    // instead of the standard 60 req/hour.
    if (serverSecrets) {
      apiUrl += '?client_id=' + serverSecrets.gh_client_id
        + '&client_secret=' + serverSecrets.gh_client_secret;
    }
    var badgeData = {text:['license',''], colorscheme:'blue'};
    // A special User-Agent is required:
    // http://developer.github.com/v3/#user-agent-required
    request(apiUrl, { headers: { 'User-Agent': 'Shields.io' } }, function(err, res, buffer) {
      if (err != null) { resolve(null); return; }
      try {
        if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
        var data = JSON.parse(buffer);
        var defaultBranch = data.default_branch;
        // Step 2: Get the SHA-1 hash of the branch tip.
        var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '/branches/' + defaultBranch;
        if (serverSecrets) {
          apiUrl += '?client_id=' + serverSecrets.gh_client_id
            + '&client_secret=' + serverSecrets.gh_client_secret;
        }
        request(apiUrl, { headers: { 'User-Agent': 'Shields.io' } }, function(err, res, buffer) {
          if (err != null) { resolve(null); return; }
          try {
            if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
            var data = JSON.parse(buffer);
            var branchTip = data.commit.sha;
            // Step 3: Get the tree at the commit.
            var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '/git/trees/' + branchTip;
            if (serverSecrets) {
              apiUrl += '?client_id=' + serverSecrets.gh_client_id
                + '&client_secret=' + serverSecrets.gh_client_secret;
            }
            request(apiUrl, { headers: { 'User-Agent': 'Shields.io' } }, function(err, res, buffer) {
              if (err != null) { resolve(null); return; }
              try {
                if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
                var data = JSON.parse(buffer);
                var treeArray = data.tree;
                var licenseBlob;
                var licenseFilename;
                // Crawl each file in the root directory
                for (var i = 0; i < treeArray.length; i++) {
                  if (treeArray[i].type != 'blob') {
                    continue;
                  }
                  if (treeArray[i].path.match(/(LICENSE|COPYING|COPYRIGHT).*/i)) {
                    licenseBlob = treeArray[i].sha;
                    licenseFilename = treeArray[i].path;
                    break;
                  }
                }
                // Could not find license file
                if (!licenseBlob) { resolve(null); return; }

                // Step 4: Get the license blob.
                var apiUrl = 'https://api.github.com/repos/' + user + '/' + repo + '/git/blobs/' + licenseBlob;
                var link = 'https://raw.githubusercontent.com/' +
                  [user, repo, defaultBranch, licenseFilename].join('/');

                if (serverSecrets) {
                  apiUrl += '?client_id=' + serverSecrets.gh_client_id
                    + '&client_secret=' + serverSecrets.gh_client_secret;
                }
                // Get the raw blob instead of JSON
                // https://developer.github.com/v3/media/
                request(apiUrl, { headers: { 'User-Agent': 'Shields.io', 'Accept': 'appplication/vnd.github.raw' } },
                function(err, res, buffer) {
                  if (err != null) { resolve(null); return; }
                  try {
                    if ((+res.headers['x-ratelimit-remaining']) === 0) { resolve(null); return; }
                    var license = guessLicense(buffer);
                    if (license) {
                      badgeData.text[1] = license;
                      resolve({
                        link: link,
                        badge: shieldsBadge(badgeData),
                        name: 'GitHub license'
                      });
                      return;
                    } else {
                      // Not a recognized license
                      resolve(null);
                      return;
                    }
                  } catch(e) { reject(e); return; }
                });
              } catch(e) { reject(e); return; }
            });
          } catch(e) { reject(e); return; }
        });
      } catch(e) { reject(e); return; }
    });
  });
};

// Key phrases for common licenses
var licensePhrases = {
  'Apache 1.1': 'apache (software )?license,? (version)? 1\\.1',
  'Apache 2': 'apache (software )?license,? (version)? 2',
  'Original BSD': 'all advertising materials mentioning features or use of this software must display the following acknowledgement',
  'New BSD': 'may be used to endorse or promote products derived from this software without specific prior written permission',
  'BSD': 'redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met',
  'AGPLv1': 'affero general public license,? version 1',
  'AGPLv3': 'affero general public license,? version 3',
  'AGPL': 'affero general public license',
  'GPLv2': 'gnu general public license,? version 2',
  'GPLv3': 'gnu general public license,? version 3',
  'GPL': 'gnu general public license',
  'LGPLv2.0': 'gnu library general public license,? version 2',
  'LGPLv2.1': 'gnu lesser general public license,? version 2\\.1',
  'LGPLv3': 'gnu lesser general public license,? version 3',
  'LGPL': 'gnu (library|lesser) general public license',
  'MIT': '\\(?(mit|expat|x11)\\)? license|permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files',
  'MPL 1.1': 'mozilla public license,? (\\(MPL\\) )?(version |v|v\\.)?1\\.1',
  'MPL 2': 'mozilla public license,? (\\(MPL\\) )?(version |v|v\\.)?2',
  'MPL': 'mozilla public license',
  'CDDL': 'common development and distribution license',
  'Eclipse': 'eclipse public license',
  'Artistic': 'artistic license',
  'zlib': 'the origin of this software must not be misrepresented',
  'ISC': 'permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted',
  'CC0': 'cc0',
  'Unlicense': 'this is free and unencumbered software released into the public domain',
}
var licenseCodes = Object.keys(licensePhrases);
var spaceMetaRegex = new RegExp(' ', 'g');

// Spaces can be any whitespace
for (var i = 0; i < licenseCodes.length; i++) {
  licensePhrases[licenseCodes[i]] = licensePhrases[licenseCodes[i]].replace(spaceMetaRegex, '\\s+');
}

// Try to guess the license based on the text and return an abbreviated name (or null if not recognized).
var guessLicense = function(text) {
  var licenseRegex;
  for (var i = 0; i < licenseCodes.length; i++) {
    licenseRegex = licensePhrases[licenseCodes[i]];
    if (text.match(new RegExp(licenseRegex, 'i'))) {
      return licenseCodes[i];
    }
  }
  // Not a recognized license
  return null;
};

var shieldsBadge = function(badgeData) {
  return ('https://img.shields.io/badge/'
    + escapeField(badgeData.text[0])
    + '-' + escapeField(badgeData.text[1])
    + '-' + badgeData.colorscheme + '.svg');
};

var escapeField = function(s) {
  return encodeURIComponent(s.replace(/-/g, '--').replace(/_/g, '__'));
};

module.exports = suggest;
<|endoftext|>


<commit_before>/**************************
 * Author : Robert Hoffmann
 * License: MIT/BSD
 * Date   : 14/01/12
 * Version: 1.0.1
 **************************
 * Sample Usages
 *
 * jQuery(selector).basicColorPicker();
 * jQuery(selector).basicColorPicker({ size: "20px" });
 * jQuery(selector).basicColorPicker(null, function(color) {
 *      alert(color);
 * });
 *
 **************************
 * Subscribe to EvenHandler
 *
 * Instead of using the callBack as shown above,
 * you can also subscribe to the eventHandler
 *
 * jQuery(selector).bind("picker:selected", function(e){
 *     alert(e.color);
 * });
 *
 * **************************
 */
(function($, undefined){
    $.fn.basicColorPicker = function (options, callBack) {
        options  = options  || { };
        callBack = callBack || function (c) { };

        var that = this;
        var guid = $.guid;
        var opt  = {
            colors  : ["#000000", "#575757", "#A0A0A0", "#FFFFFF", "#2A4BD7", "#1D6914", "#814A19", "#8126C0", "#9DAFFF", "#81C57A", "#E9DEBB", "#AD2323", "#29D0D0", "#FFEE33", "#FF9233", "#FFCDF3"],
            size    : "30px"
        };

        $.extend(opt, options);

        that.append("

");
        $(opt.colors).each(function (index, value) {
            var item = $("

");

            item.css({
                "background-color": value,
                "height"          : opt.size,
                "width"           : opt.size,

                "cursor" : "pointer",
                "float"  : "left"
            });

            item.click(function (e) {
                var selected = $(this).css("background-color");

                callBack(selected);
                $(that).triggerHandler({ type: "picker:selected", color: selected });
            });

            that.find(".picker-" + guid).append(item);
        });

        return that;
    };
})(jQuery);<commit_msg>Update demo page<commit_after>/**************************
 * Author : Robert Hoffmann
 * License: MIT/BSD
 * Date   : 14/01/12
 * Version: 1.0.1
 **************************
 * Sample Usages
 *
 * jQuery(selector).basicColorPicker();
 * jQuery(selector).basicColorPicker({ size: "20px" });
 * jQuery(selector).basicColorPicker({}, function(color) {
 *      alert(color);
 * });
 *
 **************************
 * Subscribe to EvenHandler
 *
 * Instead of using the callBack as shown above,
 * you can also subscribe to the eventHandler
 *
 * jQuery(selector).bind("picker:selected", function(e){
 *     alert(e.color);
 * });
 *
 * **************************
 */
(function($, undefined){
    $.fn.basicColorPicker = function (options, callBack) {
        options  = options  || { };
        callBack = callBack || function (c) { };

        var that = this;
        var guid = $.guid;
        var opt  = {
            colors  : ["#000000", "#575757", "#A0A0A0", "#FFFFFF", "#2A4BD7", "#1D6914", "#814A19", "#8126C0", "#9DAFFF", "#81C57A", "#E9DEBB", "#AD2323", "#29D0D0", "#FFEE33", "#FF9233", "#FFCDF3"],
            size    : "30px"
        };

        $.extend(opt, options);

        that.append("

");
        $(opt.colors).each(function (index, value) {
            var item = $("

");

            item.css({
                "background-color": value,
                "height"          : opt.size,
                "width"           : opt.size,

                "cursor" : "pointer",
                "float"  : "left"
            });

            item.click(function (e) {
                var selected = $(this).css("background-color");

                callBack(selected);
                $(that).triggerHandler({ type: "picker:selected", color: selected });
            });

            that.find(".picker-" + guid).append(item);
        });

        return that;
    };
})(jQuery);<|endoftext|>


<commit_before>/*
 * responsive-carousel
 * https://github.com/filamentgroup/responsive-carousel
 *
 * Copyright (c) 2012 Filament Group, Inc.
 * Licensed under the MIT, GPL licenses.
 */

(function($) {

	var pluginName = "carousel",
		initSelector = "." + pluginName,
		transitionAttr = "data-transition",
		prevAttr = "data-prev",
		prevTitleAttr = "data-prev-title",
		nextAttr = "data-next",
		nextTitleAttr = "data-next-title",
		transitioningClass = pluginName + "-transitioning",
		itemClass = pluginName + "-item",
		activeClass = pluginName + "-active",
		prevClass = pluginName + "-item-prev",
		nextClass = pluginName + "-item-next",
		inClass = pluginName + "-in",
		outClass = pluginName + "-out",
		navClass =  pluginName + "-nav",
		focusables = "a, input, button, select, [tabindex], textarea",
		prototype,
		cssTransitionsSupport = (function(){
			var prefixes = "webkit Moz O Ms".split( " " ),
				supported = false,
				property;

			prefixes.push("");

			while( prefixes.length ){
				property = prefixes.shift();
				property += (property === "" ? "t" : "T" )+ "ransition";

				if ( property in document.documentElement.style !== undefined && property in document.documentElement.style !== false ) {
					supported = true;
					break;
				}
			}
			return supported;
		}()),
		methods = {
			_create: function(){
				$( this )
					.trigger( "beforecreate." + pluginName )
					[ pluginName ]( "_init" )
					[ pluginName ]( "_addNextPrev" )
					.trigger( "create." + pluginName );
			},

			_init: function(){
				var trans = $( this ).attr( transitionAttr );

				if( !trans ){
					cssTransitionsSupport = false;
				}

				$( this )
					.addClass(
						pluginName +
						" " + ( trans ? pluginName + "-" + trans : "" ) + " "
					)
					.attr( "role", "region" )
					.attr( "aria-label", "carousel" )
					.children()
					.addClass( itemClass );

				$(this)[ pluginName ]( "_addNextPrevClasses" );
				$(this)[ pluginName ]( "update" );
				$( this ).data( pluginName + "data", "init"  );
			},

			_addNextPrevClasses: function(){
				var $items = $( this ).find( "." + itemClass ),
					$active = $items.filter( "." + activeClass ),
					$next = $active.next().filter( "." + itemClass ),
					$prev = $active.prev().filter( "." + itemClass );

				if( !$next.length ){
					$next = $items.first().not( "." + activeClass );
				}
				if( !$prev.length ){
					$prev = $items.last().not( "." + activeClass );
				}

				$items.removeClass( prevClass + " " + nextClass );
				$prev.addClass( prevClass );
				$next.addClass( nextClass );

			},

			next: function(){
				$( this )[ pluginName ]( "goTo", "+1" );
			},

			prev: function(){
				$( this )[ pluginName ]( "goTo", "-1" );
			},

			goTo: function( num ){
				if( this.isNavDisabled ){
					return;
				}

				// disable navigation when moving from slide to slide
				// enabled in `_transitionEnd`
				this.isNavDisabled = true;
				var $self = $(this),
					trans = $self.attr( transitionAttr ),
					reverseClass = " " + pluginName + "-" + trans + "-reverse";

				// clean up children
				$( this ).find( "." + itemClass ).removeClass( [ outClass, inClass, reverseClass ].join( " " ) );

				var $from = $( this ).find( "." + activeClass ),
					prevs = $from.index(),
					activeNum = ( prevs < 0 ? 0 : prevs ) + 1,
					nextNum = typeof( num ) === "number" ? num : activeNum + parseFloat(num),
					carouselItems = $( this ).find( "." + itemClass ),
					index = (nextNum - 1) % carouselItems.length,
					beforeGoto = "beforegoto." + pluginName,
					$to = carouselItems.eq( index ),
					reverse = ( typeof( num ) === "string" && !(parseFloat(num)) ) || nextNum > activeNum ? "" : reverseClass,
					data;

				$self.trigger( beforeGoto, data = {
					$from: $from,
					$to: $to,
					direction: nextNum > activeNum ? "forward" : "backward"
				});

				// NOTE this is a quick hack to approximate the api that jQuery provides
				//      without depending on the API (for use with similarly shaped apis)
				if( data.isDefaultPrevented ) {
					return;
				}

				if( !$to.length ){
					$to = $( this ).find( "." + itemClass )[ reverse.length ? "last" : "first" ]();
				}

				if( cssTransitionsSupport ){
					$self[ pluginName ]( "_transitionStart", $from, $to, reverse, index );
				} else {
					$self[ pluginName ]( "_transitionEnd", $from, $to, reverse, index );
				}

				// added to allow pagination to track
				$self.trigger( "goto." + pluginName, [ $to, index ] );
			},

			update: function(){
				var $items = $(this).children().not( "." + navClass );
				var $activeItem = $items.filter( "." + activeClass );
				if( !$activeItem.length ){
					$activeItem = $items.first();
				}

				$items
					.addClass( itemClass )
					.attr( "tabindex", "-1" )
					.attr( "aria-hidden", "true" )
					.attr( "role", "region" )
					.each(function( i ){
						$( this ).attr( "aria-label", "slide " + ( i + 1 ) );
						$( this ).find( focusables ).attr( "tabindex", "-1" );
					});

				$activeItem
					.addClass( activeClass )
					.attr( "tabindex", "0" )
					.each(function( i ){
						$( this ).find( focusables ).attr( "tabindex", "0" );
					})
					.attr( "aria-hidden", "false" );

				return $(this).trigger( "update." + pluginName );
			},

			_transitionStart: function( $from, $to, reverseClass, index ){
				var $self = $(this);
				var self = this;
				$to.one( navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ? "webkitTransitionEnd" : "transitionend otransitionend", function(){
					$self[ pluginName ]( "_transitionEnd", $from, $to, reverseClass, index );

					// if we're not going in reverse this is the end of the transitions, enable nav
					if( !reverseClass ){
						self.isNavDisabled = false;
					}
				});

				// if we are going in reverse we need to wait until the final transition
				// which is the old slide $from moving out
				if( reverseClass ){
					$from.one( navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ? "webkitTransitionEnd" : "transitionend otransitionend", function(){
						self.isNavDisabled = false;
					});
				}

				$(this).addClass( reverseClass );
				$from.addClass( outClass );
				$to.addClass( inClass );
			},

			_transitionEnd: function( $from, $to, reverseClass, index ){
				$( this ).removeClass( reverseClass );

				// If the slides are moving forward prevent, the previous slide from
				// transitioning slowly to the slide stack.

				// This prevents botched transitions for 2 slide carousels because,
				// unless there's a third slide to move into position from the right,
				// the slow transition to the stack can leave it in an intermediate
				// state when the user clicks "next" again.
				if( !reverseClass ){
					$from.addClass("no-transition");
					setTimeout(function(){
						$from.removeClass("no-transition");
					});
				}

				$from.removeClass( outClass + " " + activeClass );
				$to.removeClass( inClass ).addClass( activeClass );
				$( this )[ pluginName ]( "update" );
				$( this )[ pluginName ]( "_addNextPrevClasses" );
				$( this ).trigger( "aftergoto." + pluginName, [ $to, index ] );
				if( $( document.activeElement ).closest( $from[ 0 ] ).length ){
					$to.focus();
				}
			},

			_bindEventListeners: function(){
				var $elem = $( this )
					.bind( "click", function( e ){
						var targ = $( e.target ).closest( "a[href='#next'],a[href='#prev']" );
						if( targ.length ){
							$elem[ pluginName ]( targ.is( "[href='#next']" ) ? "next" : "prev" );
							e.preventDefault();
						}
					});

				return this;
			},

			_addNextPrev: function(){
				var $nav, $this = $( this ), $items, $active;

				var prev = $( this ).attr( prevAttr ) || "Prev",
					next = $( this ).attr( nextAttr ) || "Next",
					prevTitle = $( this ).attr( prevTitleAttr) || "Previous",
					nextTitle = $( this ).attr( nextTitleAttr) || "Next";

				$nav = $("" +
					"" + prev + "" +
					"" + next + "" +
					"");

				$this.trigger( "beforecreatenav." + pluginName, { $nav: $nav });

				return $this.append( $nav )[ pluginName ]( "_bindEventListeners" );
			},

			destroy: function(){
				// TODO
			}
		};

	// Collection method.
	$.fn[ pluginName ] = function( arrg, a, b, c ) {
		return this.each(function() {

			// if it's a method
			if( arrg && typeof( arrg ) === "string" ){
				return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
			}

			// don't re-init
			if( $( this ).data( pluginName + "active" ) ){
				return $( this );
			}

			// otherwise, init
			$( this ).data( pluginName + "active", true );
			$.fn[ pluginName ].prototype._create.call( this );
		});
	};

	// add methods
	prototype = $.extend( $.fn[ pluginName ].prototype, methods );
}(jQuery));
<commit_msg>different start condition for reverse<commit_after>/*
 * responsive-carousel
 * https://github.com/filamentgroup/responsive-carousel
 *
 * Copyright (c) 2012 Filament Group, Inc.
 * Licensed under the MIT, GPL licenses.
 */

(function($) {

	var pluginName = "carousel",
		initSelector = "." + pluginName,
		transitionAttr = "data-transition",
		prevAttr = "data-prev",
		prevTitleAttr = "data-prev-title",
		nextAttr = "data-next",
		nextTitleAttr = "data-next-title",
		transitioningClass = pluginName + "-transitioning",
		itemClass = pluginName + "-item",
		activeClass = pluginName + "-active",
		prevClass = pluginName + "-item-prev",
		nextClass = pluginName + "-item-next",
		inClass = pluginName + "-in",
		outClass = pluginName + "-out",
		navClass =  pluginName + "-nav",
		focusables = "a, input, button, select, [tabindex], textarea",
		prototype,
		cssTransitionsSupport = (function(){
			var prefixes = "webkit Moz O Ms".split( " " ),
				supported = false,
				property;

			prefixes.push("");

			while( prefixes.length ){
				property = prefixes.shift();
				property += (property === "" ? "t" : "T" )+ "ransition";

				if ( property in document.documentElement.style !== undefined && property in document.documentElement.style !== false ) {
					supported = true;
					break;
				}
			}
			return supported;
		}()),
		methods = {
			_create: function(){
				$( this )
					.trigger( "beforecreate." + pluginName )
					[ pluginName ]( "_init" )
					[ pluginName ]( "_addNextPrev" )
					.trigger( "create." + pluginName );
			},

			_init: function(){
				var trans = $( this ).attr( transitionAttr );

				if( !trans ){
					cssTransitionsSupport = false;
				}

				$( this )
					.addClass(
						pluginName +
						" " + ( trans ? pluginName + "-" + trans : "" ) + " "
					)
					.attr( "role", "region" )
					.attr( "aria-label", "carousel" )
					.children()
					.addClass( itemClass );

				$(this)[ pluginName ]( "_addNextPrevClasses" );
				$(this)[ pluginName ]( "update" );
				$( this ).data( pluginName + "data", "init"  );
			},

			_addNextPrevClasses: function(){
				var $items = $( this ).find( "." + itemClass ),
					$active = $items.filter( "." + activeClass ),
					$next = $active.next().filter( "." + itemClass ),
					$prev = $active.prev().filter( "." + itemClass );

				if( !$next.length ){
					$next = $items.first().not( "." + activeClass );
				}
				if( !$prev.length ){
					$prev = $items.last().not( "." + activeClass );
				}

				$items.removeClass( prevClass + " " + nextClass );
				$prev.addClass( prevClass );
				$next.addClass( nextClass );

			},

			next: function(){
				$( this )[ pluginName ]( "goTo", "+1" );
			},

			prev: function(){
				$( this )[ pluginName ]( "goTo", "-1" );
			},

			goTo: function( num ){
				if( this.isNavDisabled ){
					return;
				}

				// disable navigation when moving from slide to slide
				// enabled in `_transitionEnd`
				this.isNavDisabled = true;
				var $self = $(this),
					trans = $self.attr( transitionAttr ),
					reverseClass = " " + pluginName + "-" + trans + "-reverse";

				// clean up children
				$( this ).find( "." + itemClass ).removeClass( [ outClass, inClass, reverseClass ].join( " " ) );

				var $from = $( this ).find( "." + activeClass ),
					prevs = $from.index(),
					activeNum = ( prevs < 0 ? 0 : prevs ) + 1,
					nextNum = typeof( num ) === "number" ? num : activeNum + parseFloat(num),
					carouselItems = $( this ).find( "." + itemClass ),
					index = (nextNum - 1) % carouselItems.length,
					beforeGoto = "beforegoto." + pluginName,
					$to = carouselItems.eq( index ),
					reverse = ( typeof( num ) === "string" && !(parseFloat(num)) ) || nextNum > activeNum ? "" : reverseClass,
					data;

				$self.trigger( beforeGoto, data = {
					$from: $from,
					$to: $to,
					direction: nextNum > activeNum ? "forward" : "backward"
				});

				// NOTE this is a quick hack to approximate the api that jQuery provides
				//      without depending on the API (for use with similarly shaped apis)
				if( data.isDefaultPrevented ) {
					return;
				}

				if( !$to.length ){
					$to = $( this ).find( "." + itemClass )[ reverse.length ? "last" : "first" ]();
				}

				if( cssTransitionsSupport ){
					$self[ pluginName ]( "_transitionStart", $from, $to, reverse, index );
				} else {
					$self[ pluginName ]( "_transitionEnd", $from, $to, reverse, index );
				}

				// added to allow pagination to track
				$self.trigger( "goto." + pluginName, [ $to, index ] );
			},

			update: function(){
				var $items = $(this).children().not( "." + navClass );
				var $activeItem = $items.filter( "." + activeClass );
				if( !$activeItem.length ){
					$activeItem = $items.first();
				}

				$items
					.addClass( itemClass )
					.attr( "tabindex", "-1" )
					.attr( "aria-hidden", "true" )
					.attr( "role", "region" )
					.each(function( i ){
						$( this ).attr( "aria-label", "slide " + ( i + 1 ) );
						$( this ).find( focusables ).attr( "tabindex", "-1" );
					});

				$activeItem
					.addClass( activeClass )
					.attr( "tabindex", "0" )
					.each(function( i ){
						$( this ).find( focusables ).attr( "tabindex", "0" );
					})
					.attr( "aria-hidden", "false" );

				return $(this).trigger( "update." + pluginName );
			},

			_transitionStart: function( $from, $to, reverseClass, index ){
				var $self = $(this);
				var self = this;

				var endEvent = navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ? "webkitTransitionEnd" : "transitionend otransitionend";

				$(this).addClass( reverseClass );

				if( reverseClass ){
					// if we are going in reverse we need to wait until the final transition,
					// which is the old slide $from moving out, to re-enable transitions
					$from.one( endEvent, function(){
						self.isNavDisabled = false;
					});

					// when going in reverse we want to move the $to slide into place
					// immediately.
					$to.addClass("no-transition");
					$to.addClass( inClass );

					// once the $to slide is in place then we want to do the normal transition
					// by removing no-transition and letting the removal of classes move things
					// forward
					setTimeout(function(){
						$to.removeClass("no-transition");
						$self[ pluginName ]( "_transitionEnd", $from, $to, reverseClass, index );
					}, 20);
				} else {
					$to.one( endEvent, function(){
						$self[ pluginName ]( "_transitionEnd", $from, $to, reverseClass, index );

						// if we're not going in reverse this is the end of the transitions, enable nav
						if( !reverseClass ){
							self.isNavDisabled = false;
						}
					});

					$from.addClass( outClass );
					$to.addClass( inClass );
				}
			},

			_transitionEnd: function( $from, $to, reverseClass, index ){
				$( this ).removeClass( reverseClass );

				// If the slides are moving forward prevent, the previous slide from
				// transitioning slowly to the slide stack.

				// This prevents botched transitions for 2 slide carousels because,
				// unless there's a third slide to move into position from the right,
				// the slow transition to the stack can leave it in an intermediate
				// state when the user clicks "next" again.
				if( !reverseClass ){
					$from.addClass("no-transition");
					setTimeout(function(){
						$from.removeClass("no-transition");
					});
				}

				$from.removeClass( outClass + " " + activeClass );
				$to.removeClass( inClass ).addClass( activeClass );
				$( this )[ pluginName ]( "update" );
				$( this )[ pluginName ]( "_addNextPrevClasses" );
				$( this ).trigger( "aftergoto." + pluginName, [ $to, index ] );
				if( $( document.activeElement ).closest( $from[ 0 ] ).length ){
					$to.focus();
				}
			},

			_bindEventListeners: function(){
				var $elem = $( this )
					.bind( "click", function( e ){
						var targ = $( e.target ).closest( "a[href='#next'],a[href='#prev']" );
						if( targ.length ){
							$elem[ pluginName ]( targ.is( "[href='#next']" ) ? "next" : "prev" );
							e.preventDefault();
						}
					});

				return this;
			},

			_addNextPrev: function(){
				var $nav, $this = $( this ), $items, $active;

				var prev = $( this ).attr( prevAttr ) || "Prev",
					next = $( this ).attr( nextAttr ) || "Next",
					prevTitle = $( this ).attr( prevTitleAttr) || "Previous",
					nextTitle = $( this ).attr( nextTitleAttr) || "Next";

				$nav = $("" +
					"" + prev + "" +
					"" + next + "" +
					"");

				$this.trigger( "beforecreatenav." + pluginName, { $nav: $nav });

				return $this.append( $nav )[ pluginName ]( "_bindEventListeners" );
			},

			destroy: function(){
				// TODO
			}
		};

	// Collection method.
	$.fn[ pluginName ] = function( arrg, a, b, c ) {
		return this.each(function() {

			// if it's a method
			if( arrg && typeof( arrg ) === "string" ){
				return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
			}

			// don't re-init
			if( $( this ).data( pluginName + "active" ) ){
				return $( this );
			}

			// otherwise, init
			$( this ).data( pluginName + "active", true );
			$.fn[ pluginName ].prototype._create.call( this );
		});
	};

	// add methods
	prototype = $.extend( $.fn[ pluginName ].prototype, methods );
}(jQuery));
<|endoftext|>


<commit_before>/*
 * responsive-carousel
 * https://github.com/filamentgroup/responsive-carousel
 *
 * Copyright (c) 2012 Filament Group, Inc.
 * Licensed under the MIT, GPL licenses.
 */

(function($) {

	var pluginName = "carousel",
		initSelector = "." + pluginName,
		transitionAttr = "data-transition",
		prevAttr = "data-prev",
		prevTitleAttr = "data-prev-title",
		nextAttr = "data-next",
		nextTitleAttr = "data-next-title",
		transitioningClass = pluginName + "-transitioning",
		itemClass = pluginName + "-item",
		activeClass = pluginName + "-active",
		prevClass = pluginName + "-item-prev",
		nextClass = pluginName + "-item-next",
		inClass = pluginName + "-in",
		outClass = pluginName + "-out",
		navClass =  pluginName + "-nav",
		focusables = "a, input, button, select, [tabindex], textarea",
		prototype,
		cssTransitionsSupport = (function(){
			var prefixes = "webkit Moz O Ms".split( " " ),
				supported = false,
				property;

			prefixes.push("");

			while( prefixes.length ){
				property = prefixes.shift();
				property += (property === "" ? "t" : "T" )+ "ransition";

				if ( property in document.documentElement.style !== undefined && property in document.documentElement.style !== false ) {
					supported = true;
					break;
				}
			}
			return supported;
		}()),
		methods = {
			_create: function(){
				$( this )
					.trigger( "beforecreate." + pluginName )
					[ pluginName ]( "_init" )
					[ pluginName ]( "_addNextPrev" )
					.trigger( "create." + pluginName );
			},

			_init: function(){
				var trans = $( this ).attr( transitionAttr );

				if( !trans ){
					cssTransitionsSupport = false;
				}

				$( this )
					.addClass(
						pluginName +
						" " + ( trans ? pluginName + "-" + trans : "" ) + " "
					)
					.attr( "role", "region" )
					.attr( "aria-label", "carousel" )
					.children()
					.addClass( itemClass );

				$(this)[ pluginName ]( "_addNextPrevClasses" );
				$(this)[ pluginName ]( "update" );
				$( this ).data( pluginName + "data", "init"  );
			},

			_addNextPrevClasses: function(){
				var $items = $( this ).find( "." + itemClass ),
					$active = $items.filter( "." + activeClass ),
					$next = $active.next().filter( "." + itemClass ),
					$prev = $active.prev().filter( "." + itemClass );

				if( !$next.length ){
					$next = $items.first().not( "." + activeClass );
				}
				if( !$prev.length ){
					$prev = $items.last().not( "." + activeClass );
				}

				$items.removeClass( prevClass + " " + nextClass );
				$prev.addClass( prevClass );
				$next.addClass( nextClass );

			},

			next: function(){
				$( this )[ pluginName ]( "goTo", "+1" );
			},

			prev: function(){
				$( this )[ pluginName ]( "goTo", "-1" );
			},

			goTo: function( num ){
				if( this.isNavDisabled ){
					return;
				}

				// disable navigation when moving from slide to slide
				// enabled in `_transitionEnd`
				this.isNavDisabled = true;

				var $self = $(this),
					trans = $self.attr( transitionAttr ),
					reverseClass = " " + pluginName + "-" + trans + "-reverse";

				if( $( this ).find( "." + itemClass ).filter( "." + outClass + ", ." + inClass ).length ){
					return; // goTo doesn't work during an animation
				}

				// clean up children
				$( this ).find( "." + itemClass ).removeClass( [ outClass, inClass, reverseClass ].join( " " ) );

				var $from = $( this ).find( "." + activeClass ),
					prevs = $from.index(),
					activeNum = ( prevs < 0 ? 0 : prevs ) + 1,
					nextNum = typeof( num ) === "number" ? num : activeNum + parseFloat(num),
					carouselItems = $( this ).find( "." + itemClass ),
					index = (nextNum - 1) % carouselItems.length,
					beforeGoto = "beforegoto." + pluginName,
					$to = carouselItems.eq( index ),
					reverse = ( typeof( num ) === "string" && !(parseFloat(num)) ) || nextNum > activeNum ? "" : reverseClass,
					data;

				$self.trigger( beforeGoto, data = {
					$from: $from,
					$to: $to,
					direction: nextNum > activeNum ? "forward" : "backward"
				});

				// NOTE this is a quick hack to approximate the api that jQuery provides
				//      without depending on the API (for use with similarly shaped apis)
				if( data.isDefaultPrevented ) {
					return;
				}

				if( !$to.length ){
					$to = $( this ).find( "." + itemClass )[ reverse.length ? "last" : "first" ]();
				}

				if( cssTransitionsSupport ){
					$self[ pluginName ]( "_transitionStart", $from, $to, reverse, index );
				} else {
					$self[ pluginName ]( "_transitionEnd", $from, $to, reverse, index );
				}

				// added to allow pagination to track
				$self.trigger( "goto." + pluginName, [ $to, index ] );
			},

			update: function(){
				var $items = $(this).children().not( "." + navClass );
				var $activeItem = $items.filter( "." + activeClass );
				if( !$activeItem.length ){
					$activeItem = $items.first();
				}

				$items
					.addClass( itemClass )
					.attr( "tabindex", "-1" )
					.attr( "aria-hidden", "true" )
					.attr( "role", "region" )
					.each(function( i ){
						$( this ).attr( "aria-label", "slide " + ( i + 1 ) );
						$( this ).find( focusables ).attr( "tabindex", "-1" );
					});

				$activeItem
					.addClass( activeClass )
					.attr( "tabindex", "0" )
					.each(function( i ){
						$( this ).find( focusables ).attr( "tabindex", "0" );
					})
					.attr( "aria-hidden", "false" );

				return $(this).trigger( "update." + pluginName );
			},

			_transitionStart: function( $from, $to, reverseClass, index ){
				var $self = $(this);

				$to.one( navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ? "webkitTransitionEnd" : "transitionend otransitionend", function(){
					$self[ pluginName ]( "_transitionEnd", $from, $to, reverseClass, index );
				});

				$(this).addClass( reverseClass );
				$from.addClass( outClass );
				$to.addClass( inClass );
			},

			_transitionEnd: function( $from, $to, reverseClass, index ){
				$( this ).removeClass( reverseClass );

				// If the slides are moving forward prevent, the previous slide from
				// transitioning slowly to the slide stack.

				// This prevents botched transitions for 2 slide carousels because,
				// unless there's a third slide to move into position from the right,
				// the slow transition to the stack can leave it in an intermediate
				// state when the user clicks "next" again.
				if( !reverseClass ){
					$from.addClass("no-transition");
					setTimeout(function(){
						$from.removeClass("no-transition");
					});
				}

				$from.removeClass( outClass + " " + activeClass );
				$to.removeClass( inClass ).addClass( activeClass );
				$( this )[ pluginName ]( "update" );
				$( this )[ pluginName ]( "_addNextPrevClasses" );
				$( this ).trigger( "aftergoto." + pluginName, [ $to, index ] );
				if( $( document.activeElement ).closest( $from[ 0 ] ).length ){
					$to.focus();
				}

				this.isNavDisabled = false;
			},

			_bindEventListeners: function(){
				var $elem = $( this )
					.bind( "click", function( e ){
						var targ = $( e.target ).closest( "a[href='#next'],a[href='#prev']" );
						if( targ.length ){
							$elem[ pluginName ]( targ.is( "[href='#next']" ) ? "next" : "prev" );
							e.preventDefault();
						}
					});

				return this;
			},

			_addNextPrev: function(){
				var $nav, $this = $( this ), $items, $active;

				var prev = $( this ).attr( prevAttr ) || "Prev",
					next = $( this ).attr( nextAttr ) || "Next",
					prevTitle = $( this ).attr( prevTitleAttr) || "Previous",
					nextTitle = $( this ).attr( nextTitleAttr) || "Next";

				$nav = $("" +
					"" + prev + "" +
					"" + next + "" +
					"");

				$this.trigger( "beforecreatenav." + pluginName, { $nav: $nav });

				return $this.append( $nav )[ pluginName ]( "_bindEventListeners" );
			},

			destroy: function(){
				// TODO
			}
		};

	// Collection method.
	$.fn[ pluginName ] = function( arrg, a, b, c ) {
		return this.each(function() {

			// if it's a method
			if( arrg && typeof( arrg ) === "string" ){
				return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
			}

			// don't re-init
			if( $( this ).data( pluginName + "active" ) ){
				return $( this );
			}

			// otherwise, init
			$( this ).data( pluginName + "active", true );
			$.fn[ pluginName ].prototype._create.call( this );
		});
	};

	// add methods
	prototype = $.extend( $.fn[ pluginName ].prototype, methods );
}(jQuery));
<commit_msg>disabled at the right time everywhere<commit_after>/*
 * responsive-carousel
 * https://github.com/filamentgroup/responsive-carousel
 *
 * Copyright (c) 2012 Filament Group, Inc.
 * Licensed under the MIT, GPL licenses.
 */

(function($) {

	var pluginName = "carousel",
		initSelector = "." + pluginName,
		transitionAttr = "data-transition",
		prevAttr = "data-prev",
		prevTitleAttr = "data-prev-title",
		nextAttr = "data-next",
		nextTitleAttr = "data-next-title",
		transitioningClass = pluginName + "-transitioning",
		itemClass = pluginName + "-item",
		activeClass = pluginName + "-active",
		prevClass = pluginName + "-item-prev",
		nextClass = pluginName + "-item-next",
		inClass = pluginName + "-in",
		outClass = pluginName + "-out",
		navClass =  pluginName + "-nav",
		focusables = "a, input, button, select, [tabindex], textarea",
		prototype,
		cssTransitionsSupport = (function(){
			var prefixes = "webkit Moz O Ms".split( " " ),
				supported = false,
				property;

			prefixes.push("");

			while( prefixes.length ){
				property = prefixes.shift();
				property += (property === "" ? "t" : "T" )+ "ransition";

				if ( property in document.documentElement.style !== undefined && property in document.documentElement.style !== false ) {
					supported = true;
					break;
				}
			}
			return supported;
		}()),
		methods = {
			_create: function(){
				$( this )
					.trigger( "beforecreate." + pluginName )
					[ pluginName ]( "_init" )
					[ pluginName ]( "_addNextPrev" )
					.trigger( "create." + pluginName );
			},

			_init: function(){
				var trans = $( this ).attr( transitionAttr );

				if( !trans ){
					cssTransitionsSupport = false;
				}

				$( this )
					.addClass(
						pluginName +
						" " + ( trans ? pluginName + "-" + trans : "" ) + " "
					)
					.attr( "role", "region" )
					.attr( "aria-label", "carousel" )
					.children()
					.addClass( itemClass );

				$(this)[ pluginName ]( "_addNextPrevClasses" );
				$(this)[ pluginName ]( "update" );
				$( this ).data( pluginName + "data", "init"  );
			},

			_addNextPrevClasses: function(){
				var $items = $( this ).find( "." + itemClass ),
					$active = $items.filter( "." + activeClass ),
					$next = $active.next().filter( "." + itemClass ),
					$prev = $active.prev().filter( "." + itemClass );

				if( !$next.length ){
					$next = $items.first().not( "." + activeClass );
				}
				if( !$prev.length ){
					$prev = $items.last().not( "." + activeClass );
				}

				$items.removeClass( prevClass + " " + nextClass );
				$prev.addClass( prevClass );
				$next.addClass( nextClass );

			},

			next: function(){
				$( this )[ pluginName ]( "goTo", "+1" );
			},

			prev: function(){
				$( this )[ pluginName ]( "goTo", "-1" );
			},

			goTo: function( num ){
				if( this.isNavDisabled ){
					return;
				}

				// disable navigation when moving from slide to slide
				// enabled in `_transitionEnd`
				this.isNavDisabled = true;
				var $self = $(this),
					trans = $self.attr( transitionAttr ),
					reverseClass = " " + pluginName + "-" + trans + "-reverse";

				// clean up children
				$( this ).find( "." + itemClass ).removeClass( [ outClass, inClass, reverseClass ].join( " " ) );

				var $from = $( this ).find( "." + activeClass ),
					prevs = $from.index(),
					activeNum = ( prevs < 0 ? 0 : prevs ) + 1,
					nextNum = typeof( num ) === "number" ? num : activeNum + parseFloat(num),
					carouselItems = $( this ).find( "." + itemClass ),
					index = (nextNum - 1) % carouselItems.length,
					beforeGoto = "beforegoto." + pluginName,
					$to = carouselItems.eq( index ),
					reverse = ( typeof( num ) === "string" && !(parseFloat(num)) ) || nextNum > activeNum ? "" : reverseClass,
					data;

				$self.trigger( beforeGoto, data = {
					$from: $from,
					$to: $to,
					direction: nextNum > activeNum ? "forward" : "backward"
				});

				// NOTE this is a quick hack to approximate the api that jQuery provides
				//      without depending on the API (for use with similarly shaped apis)
				if( data.isDefaultPrevented ) {
					return;
				}

				if( !$to.length ){
					$to = $( this ).find( "." + itemClass )[ reverse.length ? "last" : "first" ]();
				}

				if( cssTransitionsSupport ){
					$self[ pluginName ]( "_transitionStart", $from, $to, reverse, index );
				} else {
					$self[ pluginName ]( "_transitionEnd", $from, $to, reverse, index );
				}

				// added to allow pagination to track
				$self.trigger( "goto." + pluginName, [ $to, index ] );
			},

			update: function(){
				var $items = $(this).children().not( "." + navClass );
				var $activeItem = $items.filter( "." + activeClass );
				if( !$activeItem.length ){
					$activeItem = $items.first();
				}

				$items
					.addClass( itemClass )
					.attr( "tabindex", "-1" )
					.attr( "aria-hidden", "true" )
					.attr( "role", "region" )
					.each(function( i ){
						$( this ).attr( "aria-label", "slide " + ( i + 1 ) );
						$( this ).find( focusables ).attr( "tabindex", "-1" );
					});

				$activeItem
					.addClass( activeClass )
					.attr( "tabindex", "0" )
					.each(function( i ){
						$( this ).find( focusables ).attr( "tabindex", "0" );
					})
					.attr( "aria-hidden", "false" );

				return $(this).trigger( "update." + pluginName );
			},

			_transitionStart: function( $from, $to, reverseClass, index ){
				var $self = $(this);
				var self = this;
				$to.one( navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ? "webkitTransitionEnd" : "transitionend otransitionend", function(){
					$self[ pluginName ]( "_transitionEnd", $from, $to, reverseClass, index );

					// if we're not going in reverse this is the end of the transitions, enable nav
					if( !reverseClass ){
						self.isNavDisabled = false;
					}
				});

				// if we are going in reverse we need to wait until the final transition
				// which is the old slide $from moving out
				if( reverseClass ){
					$from.one( navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ? "webkitTransitionEnd" : "transitionend otransitionend", function(){
						self.isNavDisabled = false;
					});
				}

				$(this).addClass( reverseClass );
				$from.addClass( outClass );
				$to.addClass( inClass );
			},

			_transitionEnd: function( $from, $to, reverseClass, index ){
				$( this ).removeClass( reverseClass );

				// If the slides are moving forward prevent, the previous slide from
				// transitioning slowly to the slide stack.

				// This prevents botched transitions for 2 slide carousels because,
				// unless there's a third slide to move into position from the right,
				// the slow transition to the stack can leave it in an intermediate
				// state when the user clicks "next" again.
				if( !reverseClass ){
					$from.addClass("no-transition");
					setTimeout(function(){
						$from.removeClass("no-transition");
					});
				}

				$from.removeClass( outClass + " " + activeClass );
				$to.removeClass( inClass ).addClass( activeClass );
				$( this )[ pluginName ]( "update" );
				$( this )[ pluginName ]( "_addNextPrevClasses" );
				$( this ).trigger( "aftergoto." + pluginName, [ $to, index ] );
				if( $( document.activeElement ).closest( $from[ 0 ] ).length ){
					$to.focus();
				}
			},

			_bindEventListeners: function(){
				var $elem = $( this )
					.bind( "click", function( e ){
						var targ = $( e.target ).closest( "a[href='#next'],a[href='#prev']" );
						if( targ.length ){
							$elem[ pluginName ]( targ.is( "[href='#next']" ) ? "next" : "prev" );
							e.preventDefault();
						}
					});

				return this;
			},

			_addNextPrev: function(){
				var $nav, $this = $( this ), $items, $active;

				var prev = $( this ).attr( prevAttr ) || "Prev",
					next = $( this ).attr( nextAttr ) || "Next",
					prevTitle = $( this ).attr( prevTitleAttr) || "Previous",
					nextTitle = $( this ).attr( nextTitleAttr) || "Next";

				$nav = $("" +
					"" + prev + "" +
					"" + next + "" +
					"");

				$this.trigger( "beforecreatenav." + pluginName, { $nav: $nav });

				return $this.append( $nav )[ pluginName ]( "_bindEventListeners" );
			},

			destroy: function(){
				// TODO
			}
		};

	// Collection method.
	$.fn[ pluginName ] = function( arrg, a, b, c ) {
		return this.each(function() {

			// if it's a method
			if( arrg && typeof( arrg ) === "string" ){
				return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
			}

			// don't re-init
			if( $( this ).data( pluginName + "active" ) ){
				return $( this );
			}

			// otherwise, init
			$( this ).data( pluginName + "active", true );
			$.fn[ pluginName ].prototype._create.call( this );
		});
	};

	// add methods
	prototype = $.extend( $.fn[ pluginName ].prototype, methods );
}(jQuery));
<|endoftext|>


<commit_before>import WidgetModel from '../models/WidgetModel';
import WidgetCollection from '../collections/WidgetCollection';
import ControlsPanel from './ControlsPanel';
import View from 'girder/views/View';
import router  from 'girder/router';
import { restRequest } from 'girder/rest';
import { renderMarkdown } from 'girder/misc';

import template from '../templates/taskRun.pug';
import '../stylesheets/taskRun.styl';

const TaskRunView = View.extend({
    events: {
        'click .g-run-task': 'execute'
    },

    initialize: function () {
        this._taskSpec = this.model.get('meta').itemTaskSpec || {};
        this._inputs = this._taskSpec.inputs || [];
        this._outputs = this._taskSpec.outputs || [];
        this._inputWidgets = new WidgetCollection();
        this._outputWidgets = new WidgetCollection();

        // Build all the widget models from the task IO spec
        this._inputWidgets.add(this._inputs.map((input) => {
            return new WidgetModel({
                type: input.type,
                title: input.name || input.id,
                id: input.id || input.name,
                description: input.description || '',
                values: input.values,
                value: input.default && input.default.data
            });
        }));

        this._outputWidgets.add(this._outputs.map((output) => {
            return new WidgetModel({
                type: output.type,
                title: output.name || output.id,
                id: output.id || output.name,
                description: output.description || ''
            });
        }));

        this._inputsPanel = new ControlsPanel({
            title: 'Configure inputs',
            collection: this._inputWidgets,
            parentView: this
        });

        this._outputsPanel = new ControlsPanel({
            title: 'Configure outputs',
            collection: this._outputWidgets,
            parentView: this
        });
    },

    render: function () {
        var hasInputs = !!this._inputs.length,
            hasOutputs = !!this._outputs.length;

        this.$el.html(template({
            item: this.model,
            hasInputs: hasInputs,
            hasOutputs: hasOutputs,
            renderMarkdown: renderMarkdown
        }));

        if (hasInputs) {
            this._inputsPanel.setElement(this.$('.g-inputs-container')).render();
        }

        if (hasOutputs) {
            this._outputsPanel.setElement(this.$('.g-outputs-container')).render();
        }
    },

    /**
     * Validates that all of the widgets are in a valid state. Displays any
     * invalid states and
     */
    validate: function () {
        let ok = true;
        const test = (model) => {
            if (!model.isValid()) {
                ok = false;
            }
        };

        // Don't short-circuit; we want to highlight *all* invalid inputs
        this._inputWidgets.each(test);
        this._outputWidgets.each(test);

        return ok;
    },

    /**
     * Translates the WidgetCollection state for the input and output widgets into the
     * appropriate girder_worker input and output bindings, then invokes the endpoint
     * to execute the task. TODO We probably want to move that translation layer down into
     * the WidgetCollection itself in the future.
     */
    execute: function (e) {
        if (!this.validate()) {
            this.$('.g-validation-failed-message').text(
                'One or more of your inputs or outputs is invalid, they are highlighted in red.');
            return;
        }
        this.$('.g-validation-failed-message').empty();
        $(e.currentTarget).attr('disabled', 'true').addClass('disabled');

        const inputs = {}, outputs = {};

        const translate = (model) => {
            const val = model.value();

            switch (model.get('type')) {
                case 'image': // This is an input
                    return {
                        mode: 'girder',
                        resource_type: 'file',
                        id: val.id
                    };
                case 'file': // This is an input
                    return {
                        mode: 'girder',
                        resource_type: 'item',
                        id: val.id
                    };
                case 'new-file': // This is an output
                    return {
                        mode: 'girder',
                        parent_id: model.value().get('folderId'),
                        parent_type: 'folder',
                        name: val.name()
                    };
                default:
                    return {
                        mode: 'inline',
                        data: model.value()
                    };
            }
        };

        this._inputWidgets.each((model) => {
            inputs[model.id] = translate(model);
        });
        this._outputWidgets.each((model) => {
            outputs[model.id] = translate(model);
        });

        restRequest({
            path: `item_task/${this.model.id}/execution`,
            type: 'POST',
            data: {
                inputs: JSON.stringify(inputs),
                outputs: JSON.stringify(outputs)
            },
            error: null
        }).done((resp) => {
            router.navigate(`job/${resp._id}`, {trigger: true});
        }).error((resp) => {
            $(e.currentTarget).attr('disabled', null).removeClass('disabled');
            this.$('.g-validation-failed-message').text('Error: ' + resp.responseJSON.message);
        });
    }
});

export default TaskRunView;
<commit_msg>Fix task submission<commit_after>import WidgetModel from '../models/WidgetModel';
import WidgetCollection from '../collections/WidgetCollection';
import ControlsPanel from './ControlsPanel';
import View from 'girder/views/View';
import router  from 'girder/router';
import { restRequest } from 'girder/rest';
import { renderMarkdown } from 'girder/misc';

import template from '../templates/taskRun.pug';
import '../stylesheets/taskRun.styl';

const TaskRunView = View.extend({
    events: {
        'click .g-run-task': 'execute'
    },

    initialize: function () {
        this._taskSpec = this.model.get('meta').itemTaskSpec || {};
        this._inputs = this._taskSpec.inputs || [];
        this._outputs = this._taskSpec.outputs || [];
        this._inputWidgets = new WidgetCollection();
        this._outputWidgets = new WidgetCollection();

        // Build all the widget models from the task IO spec
        this._inputWidgets.add(this._inputs.map((input) => {
            return new WidgetModel({
                type: input.type,
                title: input.name || input.id,
                id: input.id || input.name,
                description: input.description || '',
                values: input.values,
                value: input.default && input.default.data
            });
        }));

        this._outputWidgets.add(this._outputs.map((output) => {
            return new WidgetModel({
                type: output.type,
                title: output.name || output.id,
                id: output.id || output.name,
                description: output.description || ''
            });
        }));

        this._inputsPanel = new ControlsPanel({
            title: 'Configure inputs',
            collection: this._inputWidgets,
            parentView: this
        });

        this._outputsPanel = new ControlsPanel({
            title: 'Configure outputs',
            collection: this._outputWidgets,
            parentView: this
        });
    },

    render: function () {
        var hasInputs = !!this._inputs.length,
            hasOutputs = !!this._outputs.length;

        this.$el.html(template({
            item: this.model,
            hasInputs: hasInputs,
            hasOutputs: hasOutputs,
            renderMarkdown: renderMarkdown
        }));

        if (hasInputs) {
            this._inputsPanel.setElement(this.$('.g-inputs-container')).render();
        }

        if (hasOutputs) {
            this._outputsPanel.setElement(this.$('.g-outputs-container')).render();
        }
    },

    /**
     * Validates that all of the widgets are in a valid state. Displays any
     * invalid states and
     */
    validate: function () {
        let ok = true;
        const test = (model) => {
            if (!model.isValid()) {
                ok = false;
            }
        };

        // Don't short-circuit; we want to highlight *all* invalid inputs
        this._inputWidgets.each(test);
        this._outputWidgets.each(test);

        return ok;
    },

    /**
     * Translates the WidgetCollection state for the input and output widgets into the
     * appropriate girder_worker input and output bindings, then invokes the endpoint
     * to execute the task. TODO We probably want to move that translation layer down into
     * the WidgetCollection itself in the future.
     */
    execute: function (e) {
        if (!this.validate()) {
            this.$('.g-validation-failed-message').text(
                'One or more of your inputs or outputs is invalid, they are highlighted in red.');
            return;
        }
        this.$('.g-validation-failed-message').empty();
        $(e.currentTarget).attr('disabled', 'true').addClass('disabled');

        const inputs = {}, outputs = {};

        const translate = (model) => {
            const val = model.value();

            switch (model.get('type')) {
                case 'image': // This is an input
                    return {
                        mode: 'girder',
                        resource_type: 'file',
                        id: val.id
                    };
                case 'file': // This is an input
                    return {
                        mode: 'girder',
                        resource_type: 'item',
                        id: val.id
                    };
                case 'new-file': // This is an output
                    return {
                        mode: 'girder',
                        parent_id: val.id,
                        parent_type: 'folder',
                        name: model.get('fileName')
                    };
                default:
                    return {
                        mode: 'inline',
                        data: model.value()
                    };
            }
        };

        this._inputWidgets.each((model) => {
            inputs[model.id] = translate(model);
        });
        this._outputWidgets.each((model) => {
            outputs[model.id] = translate(model);
        });

        restRequest({
            path: `item_task/${this.model.id}/execution`,
            type: 'POST',
            data: {
                inputs: JSON.stringify(inputs),
                outputs: JSON.stringify(outputs)
            },
            error: null
        }).done((resp) => {
            router.navigate(`job/${resp._id}`, {trigger: true});
        }).error((resp) => {
            $(e.currentTarget).attr('disabled', null).removeClass('disabled');
            this.$('.g-validation-failed-message').text('Error: ' + resp.responseJSON.message);
        });
    }
});

export default TaskRunView;
<|endoftext|>


<commit_before>/* eslint-disable no-console */

import React from 'react';
import ReactDOM from 'react-dom';

import UserRepo from '../container/UserRepo';
import fetchGithubApi from './fetchGithubApi';

const lastCommitMock = require('./lastCommitMock.json');

const repoName = 'dashboard';
const repoOwnerLogin = 'lowsky';
const repo = 'lowsky/dashboard';

let content = document.getElementById('restful-content');

const githubData = {
    repo: {
        owner: {login: repoOwnerLogin},
        name: repoName,
        branches: []
    },
    user: {
        avatar_url: '',
        login: 'lowsky'
    }
};

let renderOrUpdateBranches = () => {
    if (content) {
        ReactDOM.render((

                        <UserRepo github={githubData}/>

),
            content);
    }
};

// init
renderOrUpdateBranches();

// hot-module-reloading
if (module.hot) {
    module.hot.accept('../container/UserRepo', () => {
        renderOrUpdateBranches();
    });
}

// fetch per github REST api
const { fetchRepoBranches, fetchUser } = fetchGithubApi;

fetchUser('lowsky')
    .then(user => {
        githubData.user = user;
        console.debug('fetched user data:', user);
        renderOrUpdateBranches();
    })
    .catch(ex => {
        console.log('fetching user info failed', ex);
        alert(`Error, while loading user info for user ($user) from github`); // eslint-disable-line quotes
    });

if(false)
fetchRepoBranches(repo)

Promise.resolve([{
    name: 'lowsky'
}])
    .then(branches => {
        githubData.repo = {
            branches,
            owner: { login: repoOwnerLogin },
            name: repoName
        };
        renderOrUpdateBranches();
        return branches;
    })
    .then(branches => {
        githubData.repo = {
            branches: branches.map(branch => { branch.lastCommit = lastCommitMock; return branch; })
        };
        renderOrUpdateBranches();
    })
    .catch(ex => {
        console.log('fetching branches info failed', ex);
        alert(`Error, while loading branches info for repo ($repo) from github`); // eslint-disable-line quotes
    });

<commit_msg>remove local dev artefacts<commit_after>/* eslint-disable no-console */

import React from 'react';
import ReactDOM from 'react-dom';

import UserRepo from '../container/UserRepo';
import fetchGithubApi from './fetchGithubApi';

const lastCommitMock = require('./lastCommitMock.json');

const repoName = 'dashboard';
const repoOwnerLogin = 'lowsky';
const repo = 'lowsky/dashboard';

let content = document.getElementById('restful-content');

const githubData = {
    repo: {
        owner: {login: repoOwnerLogin},
        name: repoName,
        branches: []
    },
    user: {
        avatar_url: '',
        login: 'lowsky'
    }
};

let renderOrUpdateBranches = () => {
    if (content) {
        ReactDOM.render((

                        <UserRepo github={githubData}/>

),
            content);
    }
};

// init
renderOrUpdateBranches();

// hot-module-reloading
if (module.hot) {
    module.hot.accept('../container/UserRepo', () => {
        renderOrUpdateBranches();
    });
}

// fetch per github REST api
const { fetchRepoBranches, fetchUser } = fetchGithubApi;

fetchUser('lowsky')
    .then(user => {
        githubData.user = user;
        console.debug('fetched user data:', user);
        renderOrUpdateBranches();
    })
    .catch(ex => {
        console.log('fetching user info failed', ex);
        alert(`Error, while loading user info for user ($user) from github`); // eslint-disable-line quotes
    });

fetchRepoBranches(repo)
    .then(branches => {
        githubData.repo = {
            branches,
            owner: { login: repoOwnerLogin },
            name: repoName
        };
        renderOrUpdateBranches();
        return branches;
    })
    .then(branches => {
        githubData.repo = {
            branches: branches.map(branch => { branch.lastCommit = lastCommitMock; return branch; })
        };
        renderOrUpdateBranches();
    })
    .catch(ex => {
        console.log('fetching branches info failed', ex);
        alert(`Error, while loading branches info for repo ($repo) from github`); // eslint-disable-line quotes
    });

<|endoftext|>