<commit_before>/* ************************************************************************

   qooxdoo - the new era of web development

   http://qooxdoo.org

   Copyright:
     2017 Christian Boulanger

   License:
     MIT: https://opensource.org/licenses/MIT
     See the LICENSE file in the project's top-level directory for details.

   Authors:
     * Christian Boulanger (info@bibliograph.org, @cboulanger)

************************************************************************ */

require("../Package");

require("@qooxdoo/framework");
const process = require("process");
const Search = require("github-api/dist/components/Search");
const Repository = require("github-api/dist/components/Repository");
const fetch = require("node-fetch");
const semver = require("semver");
const inquirer = require("inquirer");
const path = require("upath");

/**
 * Updates the local cache with information of available library packages
 */
qx.Class.define("qx.tool.cli.commands.package.Update", {
  extend: qx.tool.cli.commands.Package,

  statics: {

    getYargsCommand: function() {
      return {
        command: "update [repository]",
        describe: "updates information on packages from github. Has to be called before the other commands. If a package URI is supplied, only update information on that package",
        builder: {
          "file": {
            alias: "f",
            describe: "Output result to a file"
          },
          "search": {
            alias: "S",
            describe: "Search GitHub for repos (as opposed to using the cached nightly data)"
          },
          "all-versions": {
            alias: "a",
            describe: "Retrieve all releases (as opposed to the latest minor/patch release of each major release)"
          },
          "prereleases": {
            alias: "p",
            describe: "Include prereleases"
          },
          "verbose": {
            alias: "v",
            describe: "Verbose logging"
          },
          "quiet": {
            alias: "q",
            describe: "No output"
          }
        }
      };
    }
  },

  members: {

    /**
     * Updates the cache with information from GitHub.
     */
    process: async function() {
      // init
      let names = [];
      const argv = this.argv;
      const update_repo_only = argv.repository;
      if (!update_repo_only) {
        this.clearCache();
      }

      let cfg = await qx.tool.cli.ConfigDb.getInstance();
      let github = cfg.db("github", {});

      const self = this;
      // Create the cache
      if (!argv.search) {
        // Retrieve the data from the repository
        await updateFromRepository();
      } else {
        if (!github.token) {
          let response = await inquirer.prompt([
            {
              type: "input",
              name: "token",
              message: "Searching GitHub requires an API token - visit https://github.com/settings/tokens to obtain one " +
                  "(you do not need to assign any permissions, just create a token);\nWhat is your GitHub API Token ? "
            }
          ]
          );
          if (!response.token) {
            qx.tool.compiler.Console.error("You have not provided a GitHub token.");
            return;
          }
          github.token = response.token;
          cfg.save();
        }

        // Generate data from GitHub API
        await updateFromGitHubAPI();
      }

      let num_libraries = this.getCache().num_libraries;
      if (num_libraries && !argv.quiet) {
        qx.tool.compiler.Console.info(`Found ${num_libraries} releases of libraries.`);
        qx.tool.compiler.Console.info(`Run 'qx package list' in the root dir of your project to see which versions of these libraries are compatible.`);
      }

      // save cache
      if (argv.file) {
        await this.exportCache(argv.file);
      } else {
        await this.saveCache();
      }

      async function updateFromRepository() {
        if (!argv.quiet) {
          qx.tool.compiler.Console.log("Downloading cache from GitHub ...");
        }
        let url = self.getRepositoryCacheUrl();
        try {
          let res = await fetch(url);
          let data = await res.json();
          self.setCache(data);
        } catch (e) {
          throw new qx.tool.utils.Utils.UserError(e.message);
        }
      }

      async function updateFromGitHubAPI() {
        const auth = {
          token: github.token
        };
        const search = new Search({}, auth);
        let num_libraries = 0;

        // repositories
        if (!argv.quiet) {
          qx.tool.compiler.Console.log("Searching for package repositories on GitHub...");
        }

        let query = "topic:qooxdoo-package fork:true";
        if (update_repo_only) {
          query += " " + update_repo_only;
        }
        let result = await search.forRepositories({q: query});
        // backwards-compatibility
        query = "topic:qooxdoo-contrib fork:true";
        if (update_repo_only) {
          query += " " + update_repo_only;
        }
        let result2 = await search.forRepositories({q: query});
        let repos = result.data.concat(result2.data);
        let repo_lookup = {};

        let repos_data = self.getCache().repos.data;

        // iterate over repositories
        for (let repo of repos) {
          let name = repo.full_name;
          // already dealt with
          if (repo_lookup[name]) {
            continue;
          }
          repo_lookup[name] = repo;
          // if a repository name has been given, only update this repo
          if (update_repo_only && name !== update_repo_only) {
            continue;
          }
          if (argv.verbose) {
            qx.tool.compiler.Console.info(`### Found ${name} ...`);
          }
          names.push(name);
          let repository = new Repository(name, auth);
          repos_data[name] = {
            description: repo.description,
            url: repo.url,
            releases: {
              list: [],
              data: {}
            }
          };

          // get releases
          try {
            var releases_data = await repository.listReleases();
          } catch (e) {
            qx.tool.compiler.Console.error("Error retrieving releases: " + e);
            continue;
          }

          // filter releases to speed up updates
          let releases = releases_data.data
          // filter out invalid release names and prereleases unless "--all-versions"
            .filter(r => argv["all-versions"] ? true :
              (semver.valid(r.tag_name, true) && (!semver.prerelease(r.tag_name, true) || argv["prereleases"]))
            )
            // attach a clean version number
            .map(r => {
              r.version = semver.valid(r.tag_name, true) || "0.0.0";
              return r;
            })
            // sort by version number
            .sort((a, b) => semver.compare(a.version, b.version))
            // use only the latest minor/patch unless "--all-versions"
            .filter((r, i, a) => r.version !== "0.0.0" && (argv["all-versions"] ? true : (i === a.length-1 || semver.major(a[i+1].version) > semver.major(r.version))));

          let versions = releases.map(r => r.version);
          if (argv.verbose) {
            qx.tool.compiler.Console.info(`>>> Retrieved ${releases.length} release(s) of ${name}: ${versions.join(", ")}.`);
          }

          // get Manifest.json of each release to determine compatible qooxdoo versions
          for (let release of releases) {
            let tag_name = release.tag_name;
            let releases = repos_data[name].releases;

            // list of paths to manifest files, default is Manifest.json in the root dir
            let manifests = [{path: "."}];

            // can be overridden by a qoxdoo.json in the root dir
            let qooxdoo_data;
            if (argv.verbose) {
              qx.tool.compiler.Console.log(`>>> Trying to retrieve 'qooxdoo.json' for ${name} ${tag_name}...`);
            }
            try {
              // @todo check if the method can return JSON to save parsing
              qooxdoo_data = await repository.getContents(tag_name, "qooxdoo.json", true);
              if (argv.verbose) {
                qx.tool.compiler.Console.log(`>>>  File exists, checking for libraries...`);
              }
              let data = qooxdoo_data.data;
              if (typeof data == "string") {
                try {
                  data = qx.tool.utils.Json.parseJson(data);
                } catch (e) {
                  if (argv.verbose) {
                    qx.tool.compiler.Console.warn(`!!!  Parse error: ${e.message}`);
                  }
                }
              }
              // we have a list of Manifest.json paths!
              manifests = data.libraries || data.contribs; // todo remove data.contribs. eventually, only there for BC
            } catch (e) {
              // no qooxdoo.json
              if (e.message.match(/404/)) {
                if (argv.verbose) {
                  qx.tool.compiler.Console.log(`>>> No qooxdoo.json`);
                }
              } else if (argv.verbose) {
                qx.tool.compiler.Console.warn(`!!! Error: ${e.message}`);
              }
            }

            // create a list of libraries via their manifests
            for (let [index, {path:manifest_path}] of manifests.entries()) {
              let manifest_data;
              manifest_path = path.join(manifest_path, qx.tool.config.Manifest.config.fileName);
              try {
                if (argv.verbose) {
                  qx.tool.compiler.Console.log(`>>> Retrieving Manifest file '${manifest_path}' for ${name} ${tag_name}...`);
                }
                manifest_data = await repository.getContents(tag_name, manifest_path, true);
              } catch (e) {
                if (e.message.match(/404/)) {
                  if (argv.verbose) {
                    qx.tool.compiler.Console.warn(`!!!  File does not exist.`);
                  }
                } else if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! Error: ${e.message}`);
                }
                continue;
              }
              // retrieve compatible qooxdoo versions
              let data = manifest_data.data;
              // @todo check if the method can return JSON to save parsing
              if (typeof data == "string") {
                try {
                  data = qx.tool.utils.Json.parseJson(data);
                } catch (e) {
                  if (argv.verbose) {
                    qx.tool.compiler.Console.warn(`!!! Parse error: ${e.message}`);
                    qx.tool.compiler.Console.log(data);
                  }
                  continue;
                }
              }

              // qooxdoo version @deprecated
              var qx_versions = data.info["qooxdoo-versions"];
              // @deprecated
              var qx_version_range = (data.requires && (data.requires["@qooxdoo/framework"] || data.requires["qooxdoo-sdk"])) || data.info["qooxdoo-range"];
              if (argv.verbose && data.info["qooxdoo-range"]) {
                qx.tool.compiler.Console.warn(`!!! info.qooxdoo-range is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
              }
              if (argv.verbose && data.requires && data.requires["qooxdoo-sdk"]) {
                qx.tool.compiler.Console.warn(`!!! requires["qooxdoo-sdk"] is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
              }

              // provide backwards-compatibility for info.qooxdoo-versions containing the semver range
              // (to be removed)
              if (typeof qx_versions == "string" && !qx_version_range) {
                qx_version_range = qx_versions;
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! info.qooxdoo-version is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
                }
              }

              // provide backwards-compatibility for info.qooxdoo-version
              if (qx_versions instanceof Array && qx_versions.length && !qx_version_range) {
                qx_version_range = qx_versions.join(" || ");
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! Manifest key 'info.qooxdoo-version' is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
                }
              }

              if (!qx_version_range) {
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! No compatibility information, skipping...`);
                }
                continue;
              }

              if (!semver.validRange(qx_version_range, {loose: true})) {
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! Invalid compatibility information, skipping...`);
                }
                continue;
              }

              // add information to manifest index
              qx_versions = qx_version_range;
              manifests[index] = {
                path: manifest_path,
                qx_versions,
                info: data.info,
                requires: data.requires,
                provides: data.provides
              };
              num_libraries++;
              if (argv.verbose) {
                qx.tool.compiler.Console.log(`>>> ${name} ${tag_name}: Found package '${data.info.name}' (compatible with ${qx_versions})`);
              } else if (!argv.quiet) {
                process.stdout.write("."); // output dots to indicate progress
              }
            } // end iteration over manifests
            // save data in cache
            let zip_url = `https://github.com/${name}/archive/${tag_name}.zip`;
            releases.list.push(tag_name);
            releases.data[tag_name] = {
              title: release.name,
              prerelease: release.prerelease,
              manifests,
              zip_url
            };
          } // end iteration over releases
        } // end iteration over repos

        // wrap-up
        self.getCache().version = qx.tool.config.Lockfile.getInstance().getVersion();
        self.getCache().num_libraries = num_libraries;
        if (!update_repo_only) {
          self.getCache().repos.list = names.sort();
        }
        if (!argv.quiet && !argv.verbose) {
          process.stdout.write("\n");
        }
      }
    }
  }
});
<commit_msg>No longer filter out prereleases from the cache by default (#645)<commit_after>/* ************************************************************************

   qooxdoo - the new era of web development

   http://qooxdoo.org

   Copyright:
     2017 Christian Boulanger

   License:
     MIT: https://opensource.org/licenses/MIT
     See the LICENSE file in the project's top-level directory for details.

   Authors:
     * Christian Boulanger (info@bibliograph.org, @cboulanger)

************************************************************************ */

require("../Package");

require("@qooxdoo/framework");
const process = require("process");
const Search = require("github-api/dist/components/Search");
const Repository = require("github-api/dist/components/Repository");
const fetch = require("node-fetch");
const semver = require("semver");
const inquirer = require("inquirer");
const path = require("upath");

/**
 * Updates the local cache with information of available library packages
 */
qx.Class.define("qx.tool.cli.commands.package.Update", {
  extend: qx.tool.cli.commands.Package,

  statics: {

    getYargsCommand: function() {
      return {
        command: "update [repository]",
        describe: "updates information on packages from github. Has to be called before the other commands. If a package URI is supplied, only update information on that package",
        builder: {
          "file": {
            alias: "f",
            describe: "Output result to a file"
          },
          "search": {
            alias: "S",
            describe: "Search GitHub for repos (as opposed to using the cached nightly data)"
          },
          "all-versions": {
            alias: "a",
            describe: "Retrieve all releases (as opposed to the latest minor/patch release of each major release)"
          },
          "verbose": {
            alias: "v",
            describe: "Verbose logging"
          },
          "quiet": {
            alias: "q",
            describe: "No output"
          }
        }
      };
    }
  },

  members: {

    /**
     * Updates the cache with information from GitHub.
     */
    process: async function() {
      // init
      let names = [];
      const argv = this.argv;
      const update_repo_only = argv.repository;
      if (!update_repo_only) {
        this.clearCache();
      }

      let cfg = await qx.tool.cli.ConfigDb.getInstance();
      let github = cfg.db("github", {});

      const self = this;
      // Create the cache
      if (!argv.search) {
        // Retrieve the data from the repository
        await updateFromRepository();
      } else {
        if (!github.token) {
          let response = await inquirer.prompt([
            {
              type: "input",
              name: "token",
              message: "Searching GitHub requires an API token - visit https://github.com/settings/tokens to obtain one " +
                  "(you do not need to assign any permissions, just create a token);\nWhat is your GitHub API Token ? "
            }
          ]
          );
          if (!response.token) {
            qx.tool.compiler.Console.error("You have not provided a GitHub token.");
            return;
          }
          github.token = response.token;
          cfg.save();
        }

        // Generate data from GitHub API
        await updateFromGitHubAPI();
      }

      let num_libraries = this.getCache().num_libraries;
      if (num_libraries && !argv.quiet) {
        qx.tool.compiler.Console.info(`Found ${num_libraries} releases of libraries.`);
        qx.tool.compiler.Console.info(`Run 'qx package list' in the root dir of your project to see which versions of these libraries are compatible.`);
      }

      // save cache
      if (argv.file) {
        await this.exportCache(argv.file);
      } else {
        await this.saveCache();
      }

      async function updateFromRepository() {
        if (!argv.quiet) {
          qx.tool.compiler.Console.log("Downloading cache from GitHub ...");
        }
        let url = self.getRepositoryCacheUrl();
        try {
          let res = await fetch(url);
          let data = await res.json();
          self.setCache(data);
        } catch (e) {
          throw new qx.tool.utils.Utils.UserError(e.message);
        }
      }

      async function updateFromGitHubAPI() {
        const auth = {
          token: github.token
        };
        const search = new Search({}, auth);
        let num_libraries = 0;

        // repositories
        if (!argv.quiet) {
          qx.tool.compiler.Console.log("Searching for package repositories on GitHub...");
        }

        let query = "topic:qooxdoo-package fork:true";
        if (update_repo_only) {
          query += " " + update_repo_only;
        }
        let result = await search.forRepositories({q: query});
        // backwards-compatibility
        query = "topic:qooxdoo-contrib fork:true";
        if (update_repo_only) {
          query += " " + update_repo_only;
        }
        let result2 = await search.forRepositories({q: query});
        let repos = result.data.concat(result2.data);
        let repo_lookup = {};

        let repos_data = self.getCache().repos.data;

        // iterate over repositories
        for (let repo of repos) {
          let name = repo.full_name;
          // already dealt with
          if (repo_lookup[name]) {
            continue;
          }
          repo_lookup[name] = repo;
          // if a repository name has been given, only update this repo
          if (update_repo_only && name !== update_repo_only) {
            continue;
          }
          if (argv.verbose) {
            qx.tool.compiler.Console.info(`### Found ${name} ...`);
          }
          names.push(name);
          let repository = new Repository(name, auth);
          repos_data[name] = {
            description: repo.description,
            url: repo.url,
            releases: {
              list: [],
              data: {}
            }
          };

          // get releases
          try {
            var releases_data = await repository.listReleases();
          } catch (e) {
            qx.tool.compiler.Console.error("Error retrieving releases: " + e);
            continue;
          }

          // filter releases to speed up updates
          let releases = releases_data.data
          // filter out invalid release names unless "--all-versions"
            .filter(r => argv["all-versions"] ? true : semver.valid(r.tag_name, true))
            // attach a clean version number
            .map(r => {
              r.version = semver.valid(r.tag_name, true) || "0.0.0";
              return r;
            })
            // sort by version number
            .sort((a, b) => semver.compare(a.version, b.version))
            // use only the latest minor/patch unless "--all-versions"
            .filter((r, i, a) => r.version !== "0.0.0" && (argv["all-versions"] ? true : (i === a.length-1 || semver.major(a[i+1].version) > semver.major(r.version))));

          let versions = releases.map(r => r.version);
          if (argv.verbose) {
            qx.tool.compiler.Console.info(`>>> Retrieved ${releases.length} release(s) of ${name}: ${versions.join(", ")}.`);
          }

          // get Manifest.json of each release to determine compatible qooxdoo versions
          for (let release of releases) {
            let tag_name = release.tag_name;
            let releases = repos_data[name].releases;

            // list of paths to manifest files, default is Manifest.json in the root dir
            let manifests = [{path: "."}];

            // can be overridden by a qoxdoo.json in the root dir
            let qooxdoo_data;
            if (argv.verbose) {
              qx.tool.compiler.Console.log(`>>> Trying to retrieve 'qooxdoo.json' for ${name} ${tag_name}...`);
            }
            try {
              // @todo check if the method can return JSON to save parsing
              qooxdoo_data = await repository.getContents(tag_name, "qooxdoo.json", true);
              if (argv.verbose) {
                qx.tool.compiler.Console.log(`>>>  File exists, checking for libraries...`);
              }
              let data = qooxdoo_data.data;
              if (typeof data == "string") {
                try {
                  data = qx.tool.utils.Json.parseJson(data);
                } catch (e) {
                  if (argv.verbose) {
                    qx.tool.compiler.Console.warn(`!!!  Parse error: ${e.message}`);
                  }
                }
              }
              // we have a list of Manifest.json paths!
              manifests = data.libraries || data.contribs; // todo remove data.contribs. eventually, only there for BC
            } catch (e) {
              // no qooxdoo.json
              if (e.message.match(/404/)) {
                if (argv.verbose) {
                  qx.tool.compiler.Console.log(`>>> No qooxdoo.json`);
                }
              } else if (argv.verbose) {
                qx.tool.compiler.Console.warn(`!!! Error: ${e.message}`);
              }
            }

            // create a list of libraries via their manifests
            for (let [index, {path:manifest_path}] of manifests.entries()) {
              let manifest_data;
              manifest_path = path.join(manifest_path, qx.tool.config.Manifest.config.fileName);
              try {
                if (argv.verbose) {
                  qx.tool.compiler.Console.log(`>>> Retrieving Manifest file '${manifest_path}' for ${name} ${tag_name}...`);
                }
                manifest_data = await repository.getContents(tag_name, manifest_path, true);
              } catch (e) {
                if (e.message.match(/404/)) {
                  if (argv.verbose) {
                    qx.tool.compiler.Console.warn(`!!!  File does not exist.`);
                  }
                } else if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! Error: ${e.message}`);
                }
                continue;
              }
              // retrieve compatible qooxdoo versions
              let data = manifest_data.data;
              // @todo check if the method can return JSON to save parsing
              if (typeof data == "string") {
                try {
                  data = qx.tool.utils.Json.parseJson(data);
                } catch (e) {
                  if (argv.verbose) {
                    qx.tool.compiler.Console.warn(`!!! Parse error: ${e.message}`);
                    qx.tool.compiler.Console.log(data);
                  }
                  continue;
                }
              }

              // qooxdoo version @deprecated
              var qx_versions = data.info["qooxdoo-versions"];
              // @deprecated
              var qx_version_range = (data.requires && (data.requires["@qooxdoo/framework"] || data.requires["qooxdoo-sdk"])) || data.info["qooxdoo-range"];
              if (argv.verbose && data.info["qooxdoo-range"]) {
                qx.tool.compiler.Console.warn(`!!! info.qooxdoo-range is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
              }
              if (argv.verbose && data.requires && data.requires["qooxdoo-sdk"]) {
                qx.tool.compiler.Console.warn(`!!! requires["qooxdoo-sdk"] is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
              }

              // provide backwards-compatibility for info.qooxdoo-versions containing the semver range
              // (to be removed)
              if (typeof qx_versions == "string" && !qx_version_range) {
                qx_version_range = qx_versions;
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! info.qooxdoo-version is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
                }
              }

              // provide backwards-compatibility for info.qooxdoo-version
              if (qx_versions instanceof Array && qx_versions.length && !qx_version_range) {
                qx_version_range = qx_versions.join(" || ");
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! Manifest key 'info.qooxdoo-version' is deprecated. Please use the requires["@qooxdoo/framework"] key instead.`);
                }
              }

              if (!qx_version_range) {
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! No compatibility information, skipping...`);
                }
                continue;
              }

              if (!semver.validRange(qx_version_range, {loose: true})) {
                if (argv.verbose) {
                  qx.tool.compiler.Console.warn(`!!! Invalid compatibility information, skipping...`);
                }
                continue;
              }

              // add information to manifest index
              qx_versions = qx_version_range;
              manifests[index] = {
                path: manifest_path,
                qx_versions,
                info: data.info,
                requires: data.requires,
                provides: data.provides
              };
              num_libraries++;
              if (argv.verbose) {
                qx.tool.compiler.Console.log(`>>> ${name} ${tag_name}: Found package '${data.info.name}' (compatible with ${qx_versions})`);
              } else if (!argv.quiet) {
                process.stdout.write("."); // output dots to indicate progress
              }
            } // end iteration over manifests
            // save data in cache
            let zip_url = `https://github.com/${name}/archive/${tag_name}.zip`;
            releases.list.push(tag_name);
            releases.data[tag_name] = {
              title: release.name,
              prerelease: release.prerelease,
              manifests,
              zip_url
            };
          } // end iteration over releases
        } // end iteration over repos

        // wrap-up
        self.getCache().version = qx.tool.config.Lockfile.getInstance().getVersion();
        self.getCache().num_libraries = num_libraries;
        if (!update_repo_only) {
          self.getCache().repos.list = names.sort();
        }
        if (!argv.quiet && !argv.verbose) {
          process.stdout.write("\n");
        }
      }
    }
  }
});
<|endoftext|>


<commit_before><commit_msg>componentizd!<commit_after><|endoftext|>


<commit_before>new W.ScriptFile('usr/lib/webos/file.js');
new W.ScriptFile('usr/lib/webos/jquery.transit.min.js');

function EyeOfSymbiose(image) {
	this.window = $.w.window({
		title: 'Visionneuse d\'images',
		icon: new W.Icon('applications/eos'),
		width: 500,
		height: 300,
		stylesheet: 'usr/share/css/eos/main.css'
	});

	this.zoom = 1;

	var that = this;

	this.openImage = function(image, userCallback) {
		this.file = image;
		this.window.window('loading', true);
		this.window.window('option', 'title', image.getAttribute('basename')+' - Visionneuse d\'images');

		if (typeof userCallback == 'undefined') {
			userCallback = new W.Callback();
		}

		this.loadingImage = new W.LoadImage({
			images: image.getAttribute('realpath'),
			callback: function(data) {
				that.window.window('loading', false);
				delete that.loadingImage;
				if (data.IsEnd) {
					that.image.attr('src', image.getAttribute('realpath'));
					that.windowsSize();
					userCallback.success(that);
				} else {
					userCallback.error(data);
				}
			}
		});
	};

	this.previousImage = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._getImagesInDir(new W.Callback(function(images) {
			for (var i = 0; i < images.length; i++) {
				if (images[i].getAttribute('path') == that.file.getAttribute('path')) {
					break;
				}
			}
			var imageIndex = i - 1;
			if (imageIndex >= images.length) {
				imageIndex = 0;
			}
			if (imageIndex < 0) {
				imageIndex = images.length - 1;
			}
			that.openImage(images[imageIndex]);
		}));
	};

	this.nextImage = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._getImagesInDir(new W.Callback(function(images) {
			for (var i = 0; i < images.length; i++) {
				if (images[i].getAttribute('path') == that.file.getAttribute('path')) {
					break;
				}
			}
			var imageIndex = i + 1;
			if (imageIndex >= images.length) {
				imageIndex = 0;
			}
			if (imageIndex < 0) {
				imageIndex = images.length - 1;
			}
			that.openImage(images[imageIndex]);
		}));
	};

	this._getImagesInDir = function(userCallback) {
		if (typeof this.file == 'undefined') {
			userCallback.error(response);
			return;
		}

		if (typeof this.imagesInDir == 'undefined') {
			var callback = new W.Callback(function(files) {
				var images = [];
				for (var i = 0; i < files.length; i++) {
					if (jQuery.inArray(files[i].getAttribute('extension'), EyeOfSymbiose.supported) != -1) {
						images.push(files[i]);
					}
				}
				that.imagesInDir = images;
				userCallback.success(images);
			}, function(response) {
				userCallback.error(response);
			});

			var dir = this.file.getAttribute('dirname');
			W.File.listDir(dir, callback);
		} else {
			userCallback.success(that.imagesInDir);
		}
	};

	this.zoomTo = function(value) {
		if (typeof this.file == 'undefined') {
			return;
		}

		var dimentions = {
			width: that.image.width(),
			height: that.image.height()
		};
		this.zoom = value;
		this.image
			.width(dimentions.width)
			.height(dimentions.height)
			.css({
				'-moz-transform-origin': '0 0',
				'-webkit-transform-origin': '0 0',
				'-o-transform-origin': '0 0',
				'-ms-transform-origin': '0 0',
				'transform-origin': '0 0'
			}).transition({ scale: value });
	};

	this.zoomIn = function() {
		this.zoomTo(this.zoom * 1.2);
	};

	this.zoomOut = function() {
		this.zoomTo(this.zoom / 1.2);
	};

	this.realSize = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._buttons.windowsSize.toolbarWindowHeaderItem('option', 'active', false);
		this.zoomTo(1);
		this.image.css({
			'width': 'auto',
			'height': 'auto',
			'max-width': 'none',
			'max-height': 'none'
		});
	};

	this.windowsSize = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._buttons.windowsSize.toolbarWindowHeaderItem('option', 'active', true);
		this.zoomTo(1);
		this.image.css({
			'width': 'auto',
			'height': 'auto',
			'max-width': '100%',
			'max-height': '99%'
		});
	};

	var headers = this.window.window('header');

	var toolbar = $.w.toolbarWindowHeader().appendTo(headers);

	this._buttons = {};

	this._buttons.previous = $.w.toolbarWindowHeaderItem('Précédent', new W.Icon('actions/go-previous', 'button'))
		.click(function() {
			that.previousImage();
		})
		.appendTo(toolbar);

	this._buttons.next = $.w.toolbarWindowHeaderItem('Suivant', new W.Icon('actions/go-next', 'button'))
		.click(function() {
			that.nextImage();
		})
		.appendTo(toolbar);

	this._buttons.zoomIn = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-in', 'button'))
		.click(function() {
			that.zoomIn();
		})
		.appendTo(toolbar);

	this._buttons.zoomOut = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-out', 'button'))
		.click(function() {
			that.zoomOut();
		})
		.appendTo(toolbar);

	this._buttons.realSize = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-1', 'button'))
		.click(function() {
			that.realSize();
		})
		.appendTo(toolbar);

	this._buttons.windowsSize = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-page', 'button'))
		.click(function() {
			that.windowsSize();
		})
		.appendTo(toolbar);

	this.container = $.w.container()
		.addClass('eos')
		.appendTo(this.window.window('content'));

	this.container.droppable({
		accept: '*',
		scope: 'webos',
		drop: function(event, ui) {
			if (typeof ui.draggable.data('file') == 'undefined') {
				return;
			}
			that.openImage(ui.draggable.data('file')());
			return false;
		}
	});

	this.image = $('<img/>', { alt: '' }).appendTo(this.container);

	this.window.window('open');

	if (typeof image != 'undefined') {
		this.openImage(image);
	}
}

EyeOfSymbiose.supported = ['png', 'jpeg', 'jpg', 'gif'];<commit_msg>Ajout d'un commentaire descriptif pour Eye Of Symbiose.<commit_after>/**
 * Visionneur d'images Eye Of Symbiose.
 * @version 1.2
 * @author $imon
 */

new W.ScriptFile('usr/lib/webos/file.js');
new W.ScriptFile('usr/lib/webos/jquery.transit.min.js');

function EyeOfSymbiose(image) {
	this.window = $.w.window({
		title: 'Visionneuse d\'images',
		icon: new W.Icon('applications/eos'),
		width: 500,
		height: 300,
		stylesheet: 'usr/share/css/eos/main.css'
	});

	this.zoom = 1;

	var that = this;

	this.openImage = function(image, userCallback) {
		this.file = image;
		this.window.window('loading', true);
		this.window.window('option', 'title', image.getAttribute('basename')+' - Visionneuse d\'images');

		if (typeof userCallback == 'undefined') {
			userCallback = new W.Callback();
		}

		this.loadingImage = new W.LoadImage({
			images: image.getAttribute('realpath'),
			callback: function(data) {
				that.window.window('loading', false);
				delete that.loadingImage;
				if (data.IsEnd) {
					that.image.attr('src', image.getAttribute('realpath'));
					that.windowsSize();
					userCallback.success(that);
				} else {
					userCallback.error(data);
				}
			}
		});
	};

	this.previousImage = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._getImagesInDir(new W.Callback(function(images) {
			for (var i = 0; i < images.length; i++) {
				if (images[i].getAttribute('path') == that.file.getAttribute('path')) {
					break;
				}
			}
			var imageIndex = i - 1;
			if (imageIndex >= images.length) {
				imageIndex = 0;
			}
			if (imageIndex < 0) {
				imageIndex = images.length - 1;
			}
			that.openImage(images[imageIndex]);
		}));
	};

	this.nextImage = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._getImagesInDir(new W.Callback(function(images) {
			for (var i = 0; i < images.length; i++) {
				if (images[i].getAttribute('path') == that.file.getAttribute('path')) {
					break;
				}
			}
			var imageIndex = i + 1;
			if (imageIndex >= images.length) {
				imageIndex = 0;
			}
			if (imageIndex < 0) {
				imageIndex = images.length - 1;
			}
			that.openImage(images[imageIndex]);
		}));
	};

	this._getImagesInDir = function(userCallback) {
		if (typeof this.file == 'undefined') {
			userCallback.error(response);
			return;
		}

		if (typeof this.imagesInDir == 'undefined') {
			var callback = new W.Callback(function(files) {
				var images = [];
				for (var i = 0; i < files.length; i++) {
					if (jQuery.inArray(files[i].getAttribute('extension'), EyeOfSymbiose.supported) != -1) {
						images.push(files[i]);
					}
				}
				that.imagesInDir = images;
				userCallback.success(images);
			}, function(response) {
				userCallback.error(response);
			});

			var dir = this.file.getAttribute('dirname');
			W.File.listDir(dir, callback);
		} else {
			userCallback.success(that.imagesInDir);
		}
	};

	this.zoomTo = function(value) {
		if (typeof this.file == 'undefined') {
			return;
		}

		var dimentions = {
			width: that.image.width(),
			height: that.image.height()
		};
		this.zoom = value;
		this.image
			.width(dimentions.width)
			.height(dimentions.height)
			.css({
				'-moz-transform-origin': '0 0',
				'-webkit-transform-origin': '0 0',
				'-o-transform-origin': '0 0',
				'-ms-transform-origin': '0 0',
				'transform-origin': '0 0'
			}).transition({ scale: value });
	};

	this.zoomIn = function() {
		this.zoomTo(this.zoom * 1.2);
	};

	this.zoomOut = function() {
		this.zoomTo(this.zoom / 1.2);
	};

	this.realSize = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._buttons.windowsSize.toolbarWindowHeaderItem('option', 'active', false);
		this.zoomTo(1);
		this.image.css({
			'width': 'auto',
			'height': 'auto',
			'max-width': 'none',
			'max-height': 'none'
		});
	};

	this.windowsSize = function() {
		if (typeof this.file == 'undefined') {
			return;
		}

		this._buttons.windowsSize.toolbarWindowHeaderItem('option', 'active', true);
		this.zoomTo(1);
		this.image.css({
			'width': 'auto',
			'height': 'auto',
			'max-width': '100%',
			'max-height': '99%'
		});
	};

	var headers = this.window.window('header');

	var toolbar = $.w.toolbarWindowHeader().appendTo(headers);

	this._buttons = {};

	this._buttons.previous = $.w.toolbarWindowHeaderItem('Précédent', new W.Icon('actions/go-previous', 'button'))
		.click(function() {
			that.previousImage();
		})
		.appendTo(toolbar);

	this._buttons.next = $.w.toolbarWindowHeaderItem('Suivant', new W.Icon('actions/go-next', 'button'))
		.click(function() {
			that.nextImage();
		})
		.appendTo(toolbar);

	this._buttons.zoomIn = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-in', 'button'))
		.click(function() {
			that.zoomIn();
		})
		.appendTo(toolbar);

	this._buttons.zoomOut = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-out', 'button'))
		.click(function() {
			that.zoomOut();
		})
		.appendTo(toolbar);

	this._buttons.realSize = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-1', 'button'))
		.click(function() {
			that.realSize();
		})
		.appendTo(toolbar);

	this._buttons.windowsSize = $.w.toolbarWindowHeaderItem('', new W.Icon('actions/zoom-page', 'button'))
		.click(function() {
			that.windowsSize();
		})
		.appendTo(toolbar);

	this.container = $.w.container()
		.addClass('eos')
		.appendTo(this.window.window('content'));

	this.container.droppable({
		accept: '*',
		scope: 'webos',
		drop: function(event, ui) {
			if (typeof ui.draggable.data('file') == 'undefined') {
				return;
			}
			that.openImage(ui.draggable.data('file')());
			return false;
		}
	});

	this.image = $('<img/>', { alt: '' }).appendTo(this.container);

	this.window.window('open');

	if (typeof image != 'undefined') {
		this.openImage(image);
	}
}

EyeOfSymbiose.supported = ['png', 'jpeg', 'jpg', 'gif'];<|endoftext|>


<commit_before>import cn from 'classnames'
import React, { PropTypes } from 'react'
import { SecondaryText, Display1, Headline } from 'components/Text'
import styles from './Example.css'

export function Example ({ dark, children, className, description, light, title }) {
  return (

        <Headline
          className={styles.headline}
          dark={light || (!dark && !light)}
          light={dark}
          secondary
        >
          {title}
        </Headline>
        {description && (
          <SecondaryText>
            {description}
          </SecondaryText>
        )}

        {children}

  )
}

Example.propTypes = {
  children: PropTypes.node.isRequired,
  className: PropTypes.string,
  dark: PropTypes.bool,
  description: PropTypes.string,
  light: PropTypes.bool,
  title: PropTypes.string.isRequired
}

export function Examples ({ children, title }) {
  return (

        <Display1>
          {title}
        </Display1>

        {children}

  )
}

Examples.propTypes = {
  children: PropTypes.node.isRequired,
  title: PropTypes.string.isRequired
}
<commit_msg>Fix Example component theme<commit_after>import cn from 'classnames'
import React, { PropTypes } from 'react'
import { Body1, Display1, Headline } from 'components/Text'
import styles from './Example.css'

export function Example ({ dark, children, className, description, light, title }) {
  const useDark = light || (!dark && !light)
  const useLight = dark

  return (

        <Headline
          className={styles.headline}
          dark={useDark}
          light={useLight}
          secondary
        >
          {title}
        </Headline>
        {description && (
          <Body1 dark={useDark} light={useLight} secondary>
            {description}
          </Body1>
        )}

        {children}

  )
}

Example.propTypes = {
  children: PropTypes.node.isRequired,
  className: PropTypes.string,
  dark: PropTypes.bool,
  description: PropTypes.string,
  light: PropTypes.bool,
  title: PropTypes.string.isRequired
}

export function Examples ({ children, title }) {
  return (

        <Display1>
          {title}
        </Display1>

        {children}

  )
}

Examples.propTypes = {
  children: PropTypes.node.isRequired,
  title: PropTypes.string.isRequired
}
<|endoftext|>


<commit_before>/* jshint -W079 */

var moment = require('moment'),
    path   = require('path');

var scribe = require('../scribe.js')({
    createDefaultConsole : false
});

/**
 * Create a custom LogWriter
 *
 * It'll save logs under logsConsoleTwo/[user]/[logger]/[DD_MMM_YY].[logger].json
 *
 * @see lib/logWriter.js for details
 */

var myLogWriter = new scribe.LogWriter('logsConsoleTwo');

myLogWriter.getPath = function (opt) {

    return path.join(
        this.getUser(),
        opt.logger.name
    );

};

myLogWriter.getFilename = function (opt) {

    var now = moment();

    return (now.format('DD_MMM_YY')).toLowerCase() +
        '.' +
        opt.logger.name +
        '.json';

};

/**
 * Create 3 console2 instances
 */

var consoleOne = scribe.console({
    console : {
        colors : 'white'
    },
    logWriter : {
        rootPath : 'logsConsoleOne' //all logs in ./logsConsoleOne
    }
});

var consoleTwo = scribe.console(
    {
        console : {
            colors : 'inverse'
        }
    },
    myLogWriter //don't pass a logWriter config, but a custom LogWriter instead
);

var consoleThree = scribe.console({
    console : {
        colors : 'magenta'
    },
    logWriter : false //don't save logs on disk
});

/**
 * Use the consoles
 *
 * Then check logsConsoleOne and logsConsoleTwo folders
 */

consoleOne.addLogger('log');
consoleTwo.addLogger('log');
consoleThree.addLogger('log');

consoleOne.time().log('Hello World from consoleOne');
consoleTwo.time().log('Hello World from consoleTwo');
consoleThree.time().log('Hello World from consoleThree');

<commit_msg>Add doc<commit_after>/* jshint -W079 */

var moment = require('moment'),
    path   = require('path');

var scribe = require('../scribe.js')({
    createDefaultConsole : false
});

/**
 * Create a custom LogWriter
 *
 * It'll save logs under logsConsoleTwo/[user]/[logger]/[DD_MMM_YY].[logger].json
 *
 * @see lib/logWriter.js for details
 */

var myLogWriter = new scribe.LogWriter('logsConsoleTwo');

//Create own getPath and getFilename methods to erase to default ones

myLogWriter.getPath = function (opt) {

    return path.join(
        this.getUser(),
        opt.logger.name
    );

};

myLogWriter.getFilename = function (opt) {

    var now = moment();

    return (now.format('DD_MMM_YY')).toLowerCase() +
        '.' +
        opt.logger.name +
        '.json';

};

/**
 * Create 3 console2 instances
 */

var consoleOne = scribe.console({
    console : {
        colors : 'white'
    },
    logWriter : {
        rootPath : 'logsConsoleOne' //all logs in ./logsConsoleOne
    }
});

var consoleTwo = scribe.console(
    {
        console : {
            colors : 'inverse'
        }
    },
    myLogWriter //don't pass a logWriter config, but a custom LogWriter instead
);

var consoleThree = scribe.console({
    console : {
        colors : 'magenta'
    },
    logWriter : false //don't save logs on disk
});

/**
 * Use the consoles
 *
 * Then check logsConsoleOne and logsConsoleTwo folders
 */

consoleOne.addLogger('log');
consoleTwo.addLogger('log');
consoleThree.addLogger('log');

consoleOne.time().log('Hello World from consoleOne');
consoleTwo.time().log('Hello World from consoleTwo');
consoleThree.time().log('Hello World from consoleThree');

<|endoftext|>


<commit_before>'use strict';
'require uci';
'require ui';
'require form';
'require view';
'require fs';
'require tools.widgets as widgets';

function validateEmpty(section, value) {
	if (value) {
		return true;
	}
	else {
		return _('Expecting: non-empty value');
	}
}

return view.extend({
	render: function() {
		var m, s, o;

		m = new form.Map('xinetd', _('Xinetd Settings'), _('Here you can configure Xinetd services'));

		s = m.section(form.GridSection, 'service');
		s.modaltitle = _('Service definitions to be used by Xinetd');
		s.tabbed = true;
		s.anonymous = true;
		s.addremove = true;
		s.addbtntitle = _('Add new service entry');

		// The following dummy values are used to show the table overview without the hint texts
		o = s.option(form.DummyValue, 'name', _('Servicename'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'protocol', _('Protocol'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'port', _('Port'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'type', _('Type'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'server', _('Server'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'flags', _('IPv6'));
		o.cfgvalue = function(section) {
			return (uci.get('xinetd', section, 'flags') == "IPv6") ? _("yes") : _("no");
		};
		o.modalonly = false;

		o = s.option(form.DummyValue, 'disable', _('Enabled'));
		o.cfgvalue = function(section) {
			return (uci.get('xinetd', section, 'disable') == "no") ? _("yes") : _("no");
		};
		o.modalonly = false;

		s.tab('basic', _('Basic Settings'));
		s.tab('advanced', _('Advanced Settings'));

		// Now here follow the "real" values to be set in the modal (with the hint texts)

		// Basic settings
		o = s.taboption('basic', form.Value, 'name', _('Servicename'), _('Name for the service, if INTERNAL from /etc/services'));
		o.datatype = 'string';
		o.rmempty = false;
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (/^[A-Za-z0-9-_]*$/.test(value) == true)
				return true;
			return _('Invalid character');
		};

		o = s.taboption('basic', form.Flag, 'disable', _('Enabled'), _('Enable or Disable this service'));
		o.enabled  = 'no';
		o.disabled = 'yes';
		o.default  = o.enabled;
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.Flag, 'flags', _('IPv6'), _('Listen on IPv6 additional'));
		o.enabled  = 'IPv6';
		o.disabled = 'IPv4';
		o.default  = o.disabled;
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.ListValue, 'protocol', _('Protocol'), _('The protocol to be used for this service'));
		o.default = 'tcp';
		o.value('tcp', _('TCP'));
		o.value('udp', _('UDP'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.Value, 'port', _('Port'), _('The port used for this service, valid range: 0 - 65535'));
		o.datatype = 'port';
		o.depends('type', 'UNLISTED');
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.DynamicList, 'only_from', _('Allowed hosts'), _('List of allowed hosts to access this service'));
		o.datatype = 'or(ipaddr,ip6addr)';
		o.cast = 'string';
		o.modalonly = true;

		o = s.taboption('basic', form.Value, 'server', _('Server'), _('Complete path to the executable server file'));
		o.datatype = 'string';
		o.rmempty = false;
		o.modalonly = true;
		o.depends('type', 'UNLISTED');
		o.validate = validateEmpty;
		o.write = function(section, value) {
			return fs.stat(value).then(function(res) {
				if (res.type == "file") {
					uci.set('xinetd', section, 'server', value);
					return;
				} else {
					ui.addNotification(null, E('p', _('Service "%s": Invalid server file "%s"').format(section, value)), 'danger');
				}
			}).catch(function(err) {
				ui.addNotification(null, E('p', _('Service "%s": No access to server file "%s" (%s)').format(section, value, err.message)), 'danger');
				return;
			});
		};

		// Advanced settings
		o = s.taboption('advanced', form.ListValue, 'type', _('Type'), _('Type of service'));
		o.default = 'UNLISTED';
		o.value('INTERNAL', _('INTERNAL'));
		o.value('UNLISTED', _('UNLISTED'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('advanced', form.Value, 'id', _('Identification'), _('Required if a services can use tcp and udp.'));
		o.datatype = 'string';
		o.value('time-stream');
		o.value('time-dgram');
		o.value('daytime-stream');
		o.value('daytime-dgram');
		o.depends('type', 'INTERNAL');
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (value.length == 0 || /^[A-Za-z0-9_-]+$/.test(value) == true)
				return true;
			return _('Invalid character');
		};

		o = s.taboption('advanced', form.ListValue, 'wait', _('Threading behaviour'), _('Selection of the threading for this service'));
		o.default = 'no';
		o.value('yes', _('Single-Threaded Service'));
		o.value('no', _('Multi-Threaded Service'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('advanced', form.ListValue, 'socket_type', _('Socket type'), _('The type of the socket used for this service'));
		o.default = 'stream';
		o.value('stream', _('stream-based service'));
		o.value('dgram', _('datagram-based service'));
		o.value('raw', _('direct access to IP service'));
		o.value('seqpacket', _('sequential datagram transmission service'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('advanced', widgets.UserSelect, 'user', _('User (UID)'), _('User ID for the server process for this service'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('advanced', form.Value, 'server_args', _('Server arguments'), _('Additional arguments passed to the server. There is no validation of this input.'));
		o.datatype = 'string';
		o.modalonly = true;

		// Advanced settings
		o = s.taboption('advanced', form.DynamicList, 'no_access', _('Forbidden hosts'), _('List of forbidden hosts to access this service'));
		o.datatype = 'or(ipaddr,ip6addr)';
		o.cast = 'string';
		o.modalonly = true;

		o = s.taboption('advanced', form.Value, 'instances', _('Number of instances'), _('Number of simultaneously running servers for this service. Argument is any number or the keyword \'UNLIMITED\''));
		o.datatype = 'or("UNLIMITED", uinteger)';
		o.value('UNLIMITED', 'UNLIMITED');
		o.modalonly = true;

		o = s.taboption('advanced', form.DynamicList, 'access_times', _('Access times'), _('Time intervals within service is available (Format hh:mm-hh:mm)'));
		o.datatype = 'string';
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (value.length == 0 || /^([01]\d|2[0-3]):[0-5]\d-([01]\d|2[0-3]):[0-5]\d$/.test(value) == true)
				return true;

			return _('Expected \'hh:mm-hh:mm\'');

		};

		o = s.taboption('advanced', form.Value, 'cps', _('Connection limit'), _('Takes two arguments: [Number of connections per second] [Number of seconds to reenable service]'));
		o.datatype = 'string';
		o.placeholder = '50 10';
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (value.length == 0 || /^([0-9]+\s+[0-9]+$)/.test(value) == true)
				return true;

			return _('Expected \'[Number] [Number]\'');

		};

		o = s.taboption('advanced', form.MultiValue, 'log_on_success', _('Log on success'), _('Informations that should be logged for this service in case of successful connection'));
		o.value('PID', _('Server PID'));
		o.value('HOST', _('Remote host address '));
		o.value('USERID', _('User ID of the remote user'));
		o.value('EXIT', _('Server exited along with the exit status'));
		o.value('DURATION', _('Duration of a service session'));
		o.value('TRAFFIC', _('Total bytes in and out for a redirected service'));
		o.modalonly = true;

		o = s.taboption('advanced', form.MultiValue, 'log_on_failure', _('Log on failure'), _('Informations that should be logged for this service in case of a failed connection'));
		o.value('HOST', _('Remote host address '));
		o.value('USERID', _('User ID of the remote user'));
		o.value('ATTEMPT', _('Failed attempts'));
		o.modalonly = true;

		return m.render();
	}
});
<commit_msg>luci-app-xinetd: reorder service properties and add access-control tab<commit_after>'use strict';
'require uci';
'require ui';
'require form';
'require view';
'require fs';
'require tools.widgets as widgets';

function validateEmpty(section, value) {
	if (value) {
		return true;
	}
	else {
		return _('Expecting: non-empty value');
	}
}

return view.extend({
	render: function() {
		var m, s, o;

		m = new form.Map('xinetd', _('Xinetd Settings'), _('Here you can configure Xinetd services'));

		s = m.section(form.GridSection, 'service');
		s.modaltitle = _('Service definitions to be used by Xinetd');
		s.tabbed = true;
		s.anonymous = true;
		s.addremove = true;
		s.addbtntitle = _('Add new service entry');

		// The following dummy values are used to show the table overview without the hint texts
		o = s.option(form.DummyValue, 'name', _('Servicename'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'protocol', _('Protocol'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'port', _('Port'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'type', _('Type'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'server', _('Server'));
		o.modalonly = false;

		o = s.option(form.DummyValue, 'flags', _('IPv6'));
		o.cfgvalue = function(section) {
			return (uci.get('xinetd', section, 'flags') == "IPv6") ? _("yes") : _("no");
		};
		o.modalonly = false;

		o = s.option(form.DummyValue, 'disable', _('Enabled'));
		o.cfgvalue = function(section) {
			return (uci.get('xinetd', section, 'disable') == "no") ? _("yes") : _("no");
		};
		o.modalonly = false;

		s.tab('basic', _('Basic Settings'));
		s.tab('advanced', _('Advanced Settings'));
		s.tab('access', _('Access Control'));

		// Now here follow the "real" values to be set in the modal (with the hint texts)

		// Basic settings
		o = s.taboption('basic', form.Value, 'name', _('Servicename'), _('Name for the service, if INTERNAL from /etc/services'));
		o.datatype = 'string';
		o.rmempty = false;
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (/^[A-Za-z0-9-_]*$/.test(value) == true)
				return true;
			return _('Invalid character');
		};

		o = s.taboption('basic', form.Flag, 'disable', _('Enabled'), _('Enable or Disable this service'));
		o.enabled  = 'no';
		o.disabled = 'yes';
		o.default  = o.enabled;
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.Flag, 'flags', _('IPv6'), _('Listen on IPv6 additional'));
		o.enabled  = 'IPv6';
		o.disabled = 'IPv4';
		o.default  = o.disabled;
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.ListValue, 'type', _('Type'), _('Type of service'));
		o.default = 'UNLISTED';
		o.value('INTERNAL', _('INTERNAL'));
		o.value('UNLISTED', _('UNLISTED'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.Value, 'id', _('Identification'), _('Required if a services can use tcp and udp.'));
		o.datatype = 'string';
		o.value('time-stream');
		o.value('time-dgram');
		o.value('daytime-stream');
		o.value('daytime-dgram');
		o.depends('type', 'INTERNAL');
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (value.length == 0 || /^[A-Za-z0-9_-]+$/.test(value) == true)
				return true;
			return _('Invalid character');
		};

		o = s.taboption('basic', form.Value, 'port', _('Port'), _('The port used for this service, valid range: 0 - 65535'));
		o.datatype = 'port';
		o.depends('type', 'UNLISTED');
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.ListValue, 'protocol', _('Protocol'), _('The protocol to be used for this service'));
		o.default = 'tcp';
		o.value('tcp', _('TCP'));
		o.value('udp', _('UDP'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.ListValue, 'socket_type', _('Socket type'), _('The type of the socket used for this service'));
		o.default = 'stream';
		o.value('stream', _('stream-based service'));
		o.value('dgram', _('datagram-based service'));
		o.value('raw', _('direct access to IP service'));
		o.value('seqpacket', _('sequential datagram transmission service'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('basic', form.Value, 'server', _('Server'), _('Complete path to the executable server file'));
		o.datatype = 'string';
		o.rmempty = false;
		o.modalonly = true;
		o.depends('type', 'UNLISTED');
		o.validate = validateEmpty;
		o.write = function(section, value) {
			return fs.stat(value).then(function(res) {
				if (res.type == "file") {
					uci.set('xinetd', section, 'server', value);
					return;
				} else {
					ui.addNotification(null, E('p', _('Service "%s": Invalid server file "%s"').format(section, value)), 'danger');
				}
			}).catch(function(err) {
				ui.addNotification(null, E('p', _('Service "%s": No access to server file "%s" (%s)').format(section, value, err.message)), 'danger');
				return;
			});
		};

		o = s.taboption('basic', form.Value, 'server_args', _('Server arguments'), _('Additional arguments passed to the server. There is no validation of this input.'));
		o.datatype = 'string';
		o.modalonly = true;
		o.depends('type', 'UNLISTED');

		// Advanced settings
		o = s.taboption('advanced', widgets.UserSelect, 'user', _('User (UID)'), _('User ID for the server process for this service'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('advanced', form.ListValue, 'wait', _('Threading behaviour'), _('Selection of the threading for this service'));
		o.default = 'no';
		o.value('yes', _('Single-Threaded Service'));
		o.value('no', _('Multi-Threaded Service'));
		o.rmempty = false;
		o.modalonly = true;

		o = s.taboption('advanced', form.MultiValue, 'log_on_success', _('Log on success'), _('Informations that should be logged for this service in case of successful connection'));
		o.value('PID', _('Server PID'));
		o.value('HOST', _('Remote host address '));
		o.value('USERID', _('User ID of the remote user'));
		o.value('EXIT', _('Server exited along with the exit status'));
		o.value('DURATION', _('Duration of a service session'));
		o.value('TRAFFIC', _('Total bytes in and out for a redirected service'));
		o.modalonly = true;

		o = s.taboption('advanced', form.MultiValue, 'log_on_failure', _('Log on failure'), _('Informations that should be logged for this service in case of a failed connection'));
		o.value('HOST', _('Remote host address '));
		o.value('USERID', _('User ID of the remote user'));
		o.value('ATTEMPT', _('Failed attempts'));
		o.modalonly = true;

		// Access Control
		o = s.taboption('access', form.DynamicList, 'only_from', _('Allowed hosts'), _('List of allowed hosts to access this service'));
		o.datatype = 'or(ipaddr,ip6addr)';
		o.cast = 'string';
		o.modalonly = true;

		o = s.taboption('access', form.DynamicList, 'no_access', _('Forbidden hosts'), _('List of forbidden hosts to access this service'));
		o.datatype = 'or(ipaddr,ip6addr)';
		o.cast = 'string';
		o.modalonly = true;

		o = s.taboption('access', form.Value, 'instances', _('Number of instances'), _('Number of simultaneously running servers for this service. Argument is any number or the keyword \'UNLIMITED\''));
		o.datatype = 'or("UNLIMITED", uinteger)';
		o.value('UNLIMITED', 'UNLIMITED');
		o.modalonly = true;

		o = s.taboption('access', form.Value, 'cps', _('Connection limit'), _('Takes two arguments: [Number of connections per second] [Number of seconds to reenable service]'));
		o.datatype = 'string';
		o.placeholder = '50 10';
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (value.length == 0 || /^([0-9]+\s+[0-9]+$)/.test(value) == true)
				return true;
			return _('Expected \'[Number] [Number]\'');
		};

		o = s.taboption('access', form.DynamicList, 'access_times', _('Access times'), _('Time intervals within service is available (Format hh:mm-hh:mm)'));
		o.datatype = 'string';
		o.modalonly = true;
		o.validate = function(section_id, value) {
			if (value.length == 0 || /^([01]\d|2[0-3]):[0-5]\d-([01]\d|2[0-3]):[0-5]\d$/.test(value) == true)
				return true;
			return _('Expected \'hh:mm-hh:mm\'');
		};

		return m.render();
	}
});
<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/core/Emitter", "Tone/type/Type"], function(Tone){

	"use strict";

	/**
	 *  @class  Buffer loading and storage. Tone.Buffer is used internally by all
	 *          classes that make requests for audio files such as Tone.Player,
	 *          Tone.Sampler and Tone.Convolver.
	 *

	 *          Aside from load callbacks from individual buffers, Tone.Buffer
	 *  		provides static methods which keep track of the loading progress
	 *  		of all of the buffers. These methods are Tone.Buffer.on("load" / "progress" / "error")
	 *
	 *  @constructor
	 *  @extends {Tone}
	 *  @param {AudioBuffer|string} url The url to load, or the audio buffer to set.
	 *  @param {Function=} onload A callback which is invoked after the buffer is loaded.
	 *                            It's recommended to use Tone.Buffer.onload instead
	 *                            since it will give you a callback when ALL buffers are loaded.
	 *  @param {Function=} onerror The callback to invoke if there is an error
	 *  @example
	 * var buffer = new Tone.Buffer("path/to/sound.mp3", function(){
	 * 	//the buffer is now available.
	 * 	var buff = buffer.get();
	 * });
	 */
	Tone.Buffer = function(){

		var options = this.optionsObject(arguments, ["url", "onload", "onerror"], Tone.Buffer.defaults);

		/**
		 *  stores the loaded AudioBuffer
		 *  @type {AudioBuffer}
		 *  @private
		 */
		this._buffer = null;

		/**
		 *  indicates if the buffer should be reversed or not
		 *  @type {Boolean}
		 *  @private
		 */
		this._reversed = options.reverse;

		/**
		 *  The download progress indicator
		 *  @type  {Number}
		 *  @private
		 */
		this._progress = 0;

		/**
		 *  The XHR
		 *  @type  {XMLHttpRequest}
		 *  @private
		 */
		this._xhr = null;

		if (options.url instanceof AudioBuffer || options.url instanceof Tone.Buffer){
			this.set(options.url);
			// invoke the onload callback
			if (options.onload){
				options.onload(this);
			}
		} else if (this.isString(options.url)){
			this.load(options.url, options.onload, options.onerror);
		}
	};

	Tone.extend(Tone.Buffer);

	/**
	 *  the default parameters
	 *  @type {Object}
	 */
	Tone.Buffer.defaults = {
		"url" : undefined,
		"reverse" : false
	};

	/**
	 *  Pass in an AudioBuffer or Tone.Buffer to set the value
	 *  of this buffer.
	 *  @param {AudioBuffer|Tone.Buffer} buffer the buffer
	 *  @returns {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.set = function(buffer){
		if (buffer instanceof Tone.Buffer){
			this._buffer = buffer.get();
		} else {
			this._buffer = buffer;
		}
		return this;
	};

	/**
	 *  @return {AudioBuffer} The audio buffer stored in the object.
	 */
	Tone.Buffer.prototype.get = function(){
		return this._buffer;
	};

	/**
	 *  Makes an xhr reqest for the selected url then decodes
	 *  the file as an audio buffer. Invokes
	 *  the callback once the audio buffer loads.
	 *  @param {String} url The url of the buffer to load.
	 *                      filetype support depends on the
	 *                      browser.
	 *  @returns {Promise} returns a Promise which resolves with the Tone.Buffer
	 */
	Tone.Buffer.prototype.load = function(url, onload, onerror){

		var promise = new Promise(function(load, error){

			this._xhr = Tone.Buffer.load(url,

				//success
				function(buff){
					this._xhr = null;
					this.set(buff);
					load(this);
					if (onload){
						onload(this);
					}
				}.bind(this),

				//error
				function(err){
					this._xhr = null;
					error(err);
					if (onerror){
						onerror(err);
					}
				}.bind(this));

		}.bind(this));

		return promise;
	};

	/**
	 *  dispose and disconnect
	 *  @returns {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.dispose = function(){
		Tone.Emitter.prototype.dispose.call(this);
		this._buffer = null;
		if (this._xhr){
			Tone.Buffer._currentDownloads--;
			this._xhr.abort();
			this._xhr = null;
		}
		return this;
	};

	/**
	 * If the buffer is loaded or not
	 * @memberOf Tone.Buffer#
	 * @type {Boolean}
	 * @name loaded
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "loaded", {
		get : function(){
			return this.length > 0;
		},
	});

	/**
	 * The duration of the buffer.
	 * @memberOf Tone.Buffer#
	 * @type {Number}
	 * @name duration
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "duration", {
		get : function(){
			if (this._buffer){
				return this._buffer.duration;
			} else {
				return 0;
			}
		},
	});

	/**
	 * The length of the buffer in samples
	 * @memberOf Tone.Buffer#
	 * @type {Number}
	 * @name length
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "length", {
		get : function(){
			if (this._buffer){
				return this._buffer.length;
			} else {
				return 0;
			}
		},
	});

	/**
	 * The number of discrete audio channels. Returns 0 if no buffer
	 * is loaded.
	 * @memberOf Tone.Buffer#
	 * @type {Number}
	 * @name numberOfChannels
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "numberOfChannels", {
		get : function(){
			if (this._buffer){
				return this._buffer.numberOfChannels;
			} else {
				return 0;
			}
		},
	});

	/**
	 *  Set the audio buffer from the array
	 *  @param {Float32Array} array The array to fill the audio buffer
	 *  @param {Number} [channels=1] The number of channels contained in the array.
	 *                               If the channel is more than 1, the input array
	 *                               is expected to be a multidimensional array
	 *                               with dimensions equal to the number of channels.
	 *  @return {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.fromArray = function(array){
		var isMultidimensional = array[0].length > 0;
		var channels = isMultidimensional ? array.length : 1;
		var len = isMultidimensional ? array[0].length : array.length;
		var buffer = this.context.createBuffer(channels, len, this.context.sampleRate);
		if (!isMultidimensional && channels === 1){
			array = [array];
		}
		for (var c = 0; c < channels; c++){
			if (this.isFunction(buffer.copyToChannel)){
				buffer.copyToChannel(array[c], c);
			} else {
				var channel = buffer.getChannelData(c);
				var channelArray = array[c];
				for (var i = 0; i < channelArray.length; i++){
					channel[i] = channelArray[i];
				}
			}
		}
		this._buffer = buffer;
		return this;
	};

	/**
	 * 	Get the buffer as an array. Single channel buffers will return a 1-dimensional
	 * 	Float32Array, and multichannel buffers will return multidimensional arrays.
	 *  @param {Number=} channel Optionally only copy a single channel from the array.
	 *  @return {Array}
	 */
	Tone.Buffer.prototype.toArray = function(channel){
		if (this.isNumber(channel)){
			return this._buffer.getChannelData(channel);
		} else {
			var ret = [];
			for (var c = 0; c < this.numberOfChannels; c++){
				ret[c] = new Float32Array(this.length);
				if (this.isFunction(this._buffer.copyFromChannel)){
					this._buffer.copyFromChannel(ret[c], c);
				} else {
					var channelData = this._buffer.getChannelData(c);
					var retArray = ret[c];
					for (var i = 0; i < channelData.length; i++){
						retArray[i] = channelData[i];
					}
				}
			}
			if (ret.length === 1){
				return ret[0];
			} else {
				return ret;
			}
		}
	};

	/**
	 *  Cut a subsection of the array and return a buffer of the
	 *  subsection. Does not modify the original buffer
	 *  @param {Time} start The time to start the slice
	 *  @param {Time=} end The end time to slice. If none is given
	 *                     will default to the end of the buffer
	 *  @return {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.slice = function(start, end){
		end = this.defaultArg(end, this.duration);
		var startSamples = Math.floor(this.context.sampleRate * this.toSeconds(start));
		var endSamples = Math.floor(this.context.sampleRate * this.toSeconds(end));
		var replacement = [];
		for (var i = 0; i < this.numberOfChannels; i++){
			replacement[i] = this.toArray(i).slice(startSamples, endSamples);
		}
		var retBuffer = new Tone.Buffer().fromArray(replacement);
		return retBuffer;
	};

	/**
	 *  Reverse the buffer.
	 *  @private
	 *  @return {Tone.Buffer} this
	 */
	Tone.Buffer.prototype._reverse = function(){
		if (this.loaded){
			for (var i = 0; i < this._buffer.numberOfChannels; i++){
				Array.prototype.reverse.call(this._buffer.getChannelData(i));
			}
		}
		return this;
	};

	/**
	 * Reverse the buffer.
	 * @memberOf Tone.Buffer#
	 * @type {Boolean}
	 * @name reverse
	 */
	Object.defineProperty(Tone.Buffer.prototype, "reverse", {
		get : function(){
			return this._reversed;
		},
		set : function(rev){
			if (this._reversed !== rev){
				this._reversed = rev;
				this._reverse();
			}
		},
	});

	///////////////////////////////////////////////////////////////////////////
	// STATIC METHODS
	///////////////////////////////////////////////////////////////////////////

	//statically inherits Emitter methods
	Tone.Emitter.mixin(Tone.Buffer);

	/**
	 *  the static queue for all of the xhr requests
	 *  @type {Array}
	 *  @private
	 */
	Tone.Buffer._downloadQueue = [];

	/**
	 *  the total number of downloads
	 *  @type {Number}
	 *  @private
	 */
	Tone.Buffer._currentDownloads = 0;

	/**
	 *  A path which is prefixed before every url.
	 *  @type  {String}
	 *  @static
	 */
	Tone.Buffer.baseUrl = "";

	/**
	 *  Loads a url using XMLHttpRequest.
	 *  @param {String} url
	 *  @param {Function} onload
	 *  @param {Function} onerror
	 *  @param {Function} onprogress
	 *  @return {XMLHttpRequest}
	 */
	Tone.Buffer.load = function(url, onload, onerror){
		//defaults
		onload = onload || Tone.noOp;
		var errCallback = function(e){
			Tone.Buffer._currentDownloads--;
			if (onerror){
				onerror(e);
			} else {
				throw new Error(e);
			}
		};

		var request = new XMLHttpRequest();
		request.open("GET", Tone.Buffer.baseUrl + url, true);
		request.responseType = "arraybuffer";

		Tone.Buffer._currentDownloads++;
		Tone.Buffer._downloadQueue.push(request);

		request.addEventListener("load", function(){
			if (request.status === 200){
				Tone.context.decodeAudioData(request.response, function(buff) {

					request.progress = 1;
					onload(buff);

					Tone.Buffer._currentDownloads--;
					if (Tone.Buffer._currentDownloads === 0){
						// clear the downloads
						Tone.Buffer._downloadQueue = [];
						//emit the event at the end
						Tone.Buffer.emit("load");
					}

				}, function(){
					errCallback("Tone.Buffer: could not decode audio data: "+url);
				});
			} else {
				errCallback("Tone.Buffer: could not locate file: "+url);
			}
		});

		request.addEventListener("error", errCallback);

		request.addEventListener("progress", function(event){
			if (event.lengthComputable){
				request.progress = event.loaded / event.total;

				//calculate the progress
				var totalProgress = 0;
				for (var i = 0; i < Tone.Buffer._downloadQueue.length; i++){
					totalProgress += Tone.Buffer._downloadQueue[i].progress;
				}
				Tone.Buffer.emit("progress", totalProgress / Tone.Buffer._downloadQueue.length);
			}
		});

		request.send();

		return request;
	};

	/**
	 *  Checks a url's extension to see if the current browser can play that file type.
	 *  @param {String} url The url/extension to test
	 *  @return {Boolean} If the file extension can be played
	 *  @static
	 *  @example
	 * Tone.Buffer.supportsType("wav"); //returns true
	 * Tone.Buffer.supportsType("path/to/file.wav"); //returns true
	 */
	Tone.Buffer.supportsType = function(url){
		var extension = url.split(".");
		extension = extension[extension.length - 1];
		var response = document.createElement("audio").canPlayType("audio/"+extension);
		return response !== "";
	};

	return Tone.Buffer;
});<commit_msg>will emit 'progress' when there is `.lengthComputable` is false<commit_after>define(["Tone/core/Tone", "Tone/core/Emitter", "Tone/type/Type"], function(Tone){

	"use strict";

	/**
	 *  @class  Buffer loading and storage. Tone.Buffer is used internally by all
	 *          classes that make requests for audio files such as Tone.Player,
	 *          Tone.Sampler and Tone.Convolver.
	 *

	 *          Aside from load callbacks from individual buffers, Tone.Buffer
	 *  		provides static methods which keep track of the loading progress
	 *  		of all of the buffers. These methods are Tone.Buffer.on("load" / "progress" / "error")
	 *
	 *  @constructor
	 *  @extends {Tone}
	 *  @param {AudioBuffer|string} url The url to load, or the audio buffer to set.
	 *  @param {Function=} onload A callback which is invoked after the buffer is loaded.
	 *                            It's recommended to use Tone.Buffer.onload instead
	 *                            since it will give you a callback when ALL buffers are loaded.
	 *  @param {Function=} onerror The callback to invoke if there is an error
	 *  @example
	 * var buffer = new Tone.Buffer("path/to/sound.mp3", function(){
	 * 	//the buffer is now available.
	 * 	var buff = buffer.get();
	 * });
	 */
	Tone.Buffer = function(){

		var options = this.optionsObject(arguments, ["url", "onload", "onerror"], Tone.Buffer.defaults);

		/**
		 *  stores the loaded AudioBuffer
		 *  @type {AudioBuffer}
		 *  @private
		 */
		this._buffer = null;

		/**
		 *  indicates if the buffer should be reversed or not
		 *  @type {Boolean}
		 *  @private
		 */
		this._reversed = options.reverse;

		/**
		 *  The download progress indicator
		 *  @type  {Number}
		 *  @private
		 */
		this._progress = 0;

		/**
		 *  The XHR
		 *  @type  {XMLHttpRequest}
		 *  @private
		 */
		this._xhr = null;

		if (options.url instanceof AudioBuffer || options.url instanceof Tone.Buffer){
			this.set(options.url);
			// invoke the onload callback
			if (options.onload){
				options.onload(this);
			}
		} else if (this.isString(options.url)){
			this.load(options.url, options.onload, options.onerror);
		}
	};

	Tone.extend(Tone.Buffer);

	/**
	 *  the default parameters
	 *  @type {Object}
	 */
	Tone.Buffer.defaults = {
		"url" : undefined,
		"reverse" : false
	};

	/**
	 *  Pass in an AudioBuffer or Tone.Buffer to set the value
	 *  of this buffer.
	 *  @param {AudioBuffer|Tone.Buffer} buffer the buffer
	 *  @returns {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.set = function(buffer){
		if (buffer instanceof Tone.Buffer){
			this._buffer = buffer.get();
		} else {
			this._buffer = buffer;
		}
		return this;
	};

	/**
	 *  @return {AudioBuffer} The audio buffer stored in the object.
	 */
	Tone.Buffer.prototype.get = function(){
		return this._buffer;
	};

	/**
	 *  Makes an xhr reqest for the selected url then decodes
	 *  the file as an audio buffer. Invokes
	 *  the callback once the audio buffer loads.
	 *  @param {String} url The url of the buffer to load.
	 *                      filetype support depends on the
	 *                      browser.
	 *  @returns {Promise} returns a Promise which resolves with the Tone.Buffer
	 */
	Tone.Buffer.prototype.load = function(url, onload, onerror){

		var promise = new Promise(function(load, error){

			this._xhr = Tone.Buffer.load(url,

				//success
				function(buff){
					this._xhr = null;
					this.set(buff);
					load(this);
					if (onload){
						onload(this);
					}
				}.bind(this),

				//error
				function(err){
					this._xhr = null;
					error(err);
					if (onerror){
						onerror(err);
					}
				}.bind(this));

		}.bind(this));

		return promise;
	};

	/**
	 *  dispose and disconnect
	 *  @returns {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.dispose = function(){
		Tone.Emitter.prototype.dispose.call(this);
		this._buffer = null;
		if (this._xhr){
			Tone.Buffer._currentDownloads--;
			this._xhr.abort();
			this._xhr = null;
		}
		return this;
	};

	/**
	 * If the buffer is loaded or not
	 * @memberOf Tone.Buffer#
	 * @type {Boolean}
	 * @name loaded
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "loaded", {
		get : function(){
			return this.length > 0;
		},
	});

	/**
	 * The duration of the buffer.
	 * @memberOf Tone.Buffer#
	 * @type {Number}
	 * @name duration
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "duration", {
		get : function(){
			if (this._buffer){
				return this._buffer.duration;
			} else {
				return 0;
			}
		},
	});

	/**
	 * The length of the buffer in samples
	 * @memberOf Tone.Buffer#
	 * @type {Number}
	 * @name length
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "length", {
		get : function(){
			if (this._buffer){
				return this._buffer.length;
			} else {
				return 0;
			}
		},
	});

	/**
	 * The number of discrete audio channels. Returns 0 if no buffer
	 * is loaded.
	 * @memberOf Tone.Buffer#
	 * @type {Number}
	 * @name numberOfChannels
	 * @readOnly
	 */
	Object.defineProperty(Tone.Buffer.prototype, "numberOfChannels", {
		get : function(){
			if (this._buffer){
				return this._buffer.numberOfChannels;
			} else {
				return 0;
			}
		},
	});

	/**
	 *  Set the audio buffer from the array
	 *  @param {Float32Array} array The array to fill the audio buffer
	 *  @param {Number} [channels=1] The number of channels contained in the array.
	 *                               If the channel is more than 1, the input array
	 *                               is expected to be a multidimensional array
	 *                               with dimensions equal to the number of channels.
	 *  @return {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.fromArray = function(array){
		var isMultidimensional = array[0].length > 0;
		var channels = isMultidimensional ? array.length : 1;
		var len = isMultidimensional ? array[0].length : array.length;
		var buffer = this.context.createBuffer(channels, len, this.context.sampleRate);
		if (!isMultidimensional && channels === 1){
			array = [array];
		}
		for (var c = 0; c < channels; c++){
			if (this.isFunction(buffer.copyToChannel)){
				buffer.copyToChannel(array[c], c);
			} else {
				var channel = buffer.getChannelData(c);
				var channelArray = array[c];
				for (var i = 0; i < channelArray.length; i++){
					channel[i] = channelArray[i];
				}
			}
		}
		this._buffer = buffer;
		return this;
	};

	/**
	 * 	Get the buffer as an array. Single channel buffers will return a 1-dimensional
	 * 	Float32Array, and multichannel buffers will return multidimensional arrays.
	 *  @param {Number=} channel Optionally only copy a single channel from the array.
	 *  @return {Array}
	 */
	Tone.Buffer.prototype.toArray = function(channel){
		if (this.isNumber(channel)){
			return this._buffer.getChannelData(channel);
		} else {
			var ret = [];
			for (var c = 0; c < this.numberOfChannels; c++){
				ret[c] = new Float32Array(this.length);
				if (this.isFunction(this._buffer.copyFromChannel)){
					this._buffer.copyFromChannel(ret[c], c);
				} else {
					var channelData = this._buffer.getChannelData(c);
					var retArray = ret[c];
					for (var i = 0; i < channelData.length; i++){
						retArray[i] = channelData[i];
					}
				}
			}
			if (ret.length === 1){
				return ret[0];
			} else {
				return ret;
			}
		}
	};

	/**
	 *  Cut a subsection of the array and return a buffer of the
	 *  subsection. Does not modify the original buffer
	 *  @param {Time} start The time to start the slice
	 *  @param {Time=} end The end time to slice. If none is given
	 *                     will default to the end of the buffer
	 *  @return {Tone.Buffer} this
	 */
	Tone.Buffer.prototype.slice = function(start, end){
		end = this.defaultArg(end, this.duration);
		var startSamples = Math.floor(this.context.sampleRate * this.toSeconds(start));
		var endSamples = Math.floor(this.context.sampleRate * this.toSeconds(end));
		var replacement = [];
		for (var i = 0; i < this.numberOfChannels; i++){
			replacement[i] = this.toArray(i).slice(startSamples, endSamples);
		}
		var retBuffer = new Tone.Buffer().fromArray(replacement);
		return retBuffer;
	};

	/**
	 *  Reverse the buffer.
	 *  @private
	 *  @return {Tone.Buffer} this
	 */
	Tone.Buffer.prototype._reverse = function(){
		if (this.loaded){
			for (var i = 0; i < this._buffer.numberOfChannels; i++){
				Array.prototype.reverse.call(this._buffer.getChannelData(i));
			}
		}
		return this;
	};

	/**
	 * Reverse the buffer.
	 * @memberOf Tone.Buffer#
	 * @type {Boolean}
	 * @name reverse
	 */
	Object.defineProperty(Tone.Buffer.prototype, "reverse", {
		get : function(){
			return this._reversed;
		},
		set : function(rev){
			if (this._reversed !== rev){
				this._reversed = rev;
				this._reverse();
			}
		},
	});

	///////////////////////////////////////////////////////////////////////////
	// STATIC METHODS
	///////////////////////////////////////////////////////////////////////////

	//statically inherits Emitter methods
	Tone.Emitter.mixin(Tone.Buffer);

	/**
	 *  the static queue for all of the xhr requests
	 *  @type {Array}
	 *  @private
	 */
	Tone.Buffer._downloadQueue = [];

	/**
	 *  the total number of downloads
	 *  @type {Number}
	 *  @private
	 */
	Tone.Buffer._currentDownloads = 0;

	/**
	 *  A path which is prefixed before every url.
	 *  @type  {String}
	 *  @static
	 */
	Tone.Buffer.baseUrl = "";

	/**
	 *  Loads a url using XMLHttpRequest.
	 *  @param {String} url
	 *  @param {Function} onload
	 *  @param {Function} onerror
	 *  @param {Function} onprogress
	 *  @return {XMLHttpRequest}
	 */
	Tone.Buffer.load = function(url, onload, onerror){
		//defaults
		onload = onload || Tone.noOp;
		var errCallback = function(e){
			Tone.Buffer._currentDownloads--;
			if (onerror){
				onerror(e);
			} else {
				throw new Error(e);
			}
		};

		function onProgress(){
			//calculate the progress
			var totalProgress = 0;
			for (var i = 0; i < Tone.Buffer._downloadQueue.length; i++){
				totalProgress += Tone.Buffer._downloadQueue[i].progress;
			}
			Tone.Buffer.emit("progress", totalProgress / Tone.Buffer._downloadQueue.length);
		}

		var request = new XMLHttpRequest();
		request.open("GET", Tone.Buffer.baseUrl + url, true);
		request.responseType = "arraybuffer";

		Tone.Buffer._currentDownloads++;
		Tone.Buffer._downloadQueue.push(request);

		request.addEventListener("load", function(){
			if (request.status === 200){
				Tone.context.decodeAudioData(request.response, function(buff) {

					request.progress = 1;
					onProgress();
					onload(buff);

					Tone.Buffer._currentDownloads--;
					if (Tone.Buffer._currentDownloads === 0){
						// clear the downloads
						Tone.Buffer._downloadQueue = [];
						//emit the event at the end
						Tone.Buffer.emit("load");
					}

				}, function(){
					errCallback("Tone.Buffer: could not decode audio data: "+url);
				});
			} else {
				errCallback("Tone.Buffer: could not locate file: "+url);
			}
		});

		request.addEventListener("error", errCallback);

		request.addEventListener("progress", function(event){
			if (event.lengthComputable){
				request.progress = event.loaded / event.total;
				onProgress();
			}
		});

		request.send();

		return request;
	};

	/**
	 *  Checks a url's extension to see if the current browser can play that file type.
	 *  @param {String} url The url/extension to test
	 *  @return {Boolean} If the file extension can be played
	 *  @static
	 *  @example
	 * Tone.Buffer.supportsType("wav"); //returns true
	 * Tone.Buffer.supportsType("path/to/file.wav"); //returns true
	 */
	Tone.Buffer.supportsType = function(url){
		var extension = url.split(".");
		extension = extension[extension.length - 1];
		var response = document.createElement("audio").canPlayType("audio/"+extension);
		return response !== "";
	};

	return Tone.Buffer;
});<|endoftext|>


<commit_before>import { trackList } from './globals';
import { viewport } from './viewport';

/**
 * Helper factory delivering the user scrolled distance of an element.
 *
 * @param {object} dimensions: elements dimensions
 * @param {object} view: object containing window information
 * @return {object} the distance the element has travelled because of user scroll
 */
const calculateScrolled = (dimensions, view) => view.scroll.y - dimensions.top + view.dimensions.height;

/**
 * Helper factory determining if an element should be redrawn
 *
 * @param {object} rect: an elements boundingClientRect.
 * @param {object} view: view object containing window pageYoffset and innerheight
 * @return {boolean} deciding if an element should be redrawn.
 */
const shouldRedraw = (rect, view) => {
	const startPoint = rect.top - view.dimensions.height;
	const endPoint = rect.bottom;

	return view.scroll.y > startPoint && view.scroll.y < endPoint;
};

/**
 * Function initiating tracked elements callback and exposing
 * needed parameters if their condition(s) are met.
 */
export default (forceAll = false) => {
	for (let i = trackList.length - 1; i >= 0; i--) {
		const item = trackList[i];
		const scrolled = (typeof item.config.calculateScrolled === 'function')
			? item.config.calculateScrolled(item.dimensions, viewport)
			: calculateScrolled(item.dimensions, viewport);
		let initiateCallback = Boolean(forceAll);

		if (!forceAll) {
			if (typeof item.config.shouldRedraw !== 'undefined') {
				if (typeof item.config.shouldRedraw === 'function') {
					initiateCallback = item.config.shouldRedraw(item.dimensions, viewport);
				} else {
					initiateCallback = Boolean(item.config.shouldRedraw);
				}
			} else {
				initiateCallback = shouldRedraw(item.dimensions, viewport);
			}
		}

		if (initiateCallback) {
			item.callback(
				scrolled,
				item.dimensions,
				viewport);
		}
	}
};
<commit_msg>Eslint<commit_after>import { trackList } from './globals';
import { viewport } from './viewport';

/**
 * Helper factory delivering the user scrolled distance of an element.
 *
 * @param {object} dimensions: elements dimensions
 * @param {object} view: object containing window information
 * @return {object} the distance the element has travelled because of user scroll
 */
const calculateScrolled = (dimensions, view) =>
	view.scroll.y - dimensions.top + view.dimensions.height;

/**
 * Helper factory determining if an element should be redrawn
 *
 * @param {object} rect: an elements boundingClientRect.
 * @param {object} view: view object containing window pageYoffset and innerheight
 * @return {boolean} deciding if an element should be redrawn.
 */
const shouldRedraw = (rect, view) => {
	const startPoint = rect.top - view.dimensions.height;
	const endPoint = rect.bottom;

	return view.scroll.y > startPoint && view.scroll.y < endPoint;
};

/**
 * Function initiating tracked elements callback and exposing
 * needed parameters if their condition(s) are met.
 */
export default (forceAll = false) => {
	for (let i = trackList.length - 1; i >= 0; i--) {
		const item = trackList[i];
		const scrolled = (typeof item.config.calculateScrolled === 'function')
			? item.config.calculateScrolled(item.dimensions, viewport)
			: calculateScrolled(item.dimensions, viewport);
		let initiateCallback = Boolean(forceAll);

		if (!forceAll) {
			if (typeof item.config.shouldRedraw !== 'undefined') {
				if (typeof item.config.shouldRedraw === 'function') {
					initiateCallback = item.config.shouldRedraw(item.dimensions, viewport);
				} else {
					initiateCallback = Boolean(item.config.shouldRedraw);
				}
			} else {
				initiateCallback = shouldRedraw(item.dimensions, viewport);
			}
		}

		if (initiateCallback) {
			item.callback(
				scrolled,
				item.dimensions,
				viewport);
		}
	}
};
<|endoftext|>


<commit_before>// HubBub client code
// From: https://github.com/almost/hubbub/
// Copyright: Thomas Parslow 2014 (tom@almostobsolete.net)
// License: MIT

(function (hubbub) {
  "use strict";

  var defaults = {
    post: window.location.pathname
  };

  // Send a comment, reports success or failure to the callbacks
  function sendComment(options,  success, failure) {
    var endpoint = options.endpoint || defaults.endpoint,
        comment = options.comment || defaults.comment,
        metadata = options.metadata || defaults.metadata,
        post = options.post || defaults.post;

    var xmlhttp = new XMLHttpRequest();
    // TODO: Make this configurable!
    xmlhttp.open("POST", endpoint, true);
    xmlhttp.setRequestHeader("Content-type", "application/json");

    xmlhttp.onload = function (e) {
      if (xmlhttp.readyState === 4) {
        if (xmlhttp.status >= 200 && xmlhttp.status < 300) {
          var response = JSON.parse(xmlhttp.responseText);
          if (success) success(response);
        } else {
          if (failure) failure(xmlhttp);
        }
      }
    };

    xmlhttp.onerror = function (e) {
      failure(xmlhttp, e);
    };

    xmlhttp.send(JSON.stringify({metadata: metadata, comment: comment, post: post}));
  }

  // Send a comment given in the fields of a form in the DOM
  function sendForm(form, success, failure) {
    var metadata = {}, match;

    for (var i = 0; i < form.length; i++) {
      match = /^metadata_(.*)/.exec(form[i].name);
      if (match) {
        metadata[match[1]] = form[i].value;
      }
    }

    sendComment({endpoint: form.action, comment: form.comment.value, metadata: metadata}, success, failure);
  }

  // Trap all submit events and check for a data-hubbub attribute, if
  // one exists then send a comment from the form.
  function onSubmit (evt) {
    var form = evt.target;
    if (!form.getAttribute('data-hubbub')) {
      // These aren't the forms you're looking for
      return;
    }
    var previewContainer = document.querySelector(evt.target.getAttribute('data-hubbub'));
    evt.preventDefault();

    if (!form.comment) {
      // If there's no comment then just ignore the submit
      return;
    }

    // Add status class while we send
    form.className = form.className + " hubbub-sending";

    sendForm(form, success, failure);

    function removeClass() {
      form.className = form.className.split(' ').filter(function (cls) {
        return cls !== 'hubbub-sending';
      })
    }

    function success(response) {
      removeClass();
      // Clear the comment field
      form.comment.value = '';
      if (previewContainer) {
        var commentEl = document.createElement('div');
        commentEl.className = "hubbub-pending hubbub-added";
        commentEl.innerHTML = response.html;
        previewContainer.appendChild(commentEl);

        // Remove the hubbub-added class to allow CSS transitions to
        // work
        setTimeout(function () {
          commentEl.className = "hubbub-pending";
        }, 100);
      }
    }

    function failure(xmlhttp) {
      removeClass();
      alert("Failed to send comment.");
    }
  }

  document.addEventListener('submit', onSubmit);

  function hubub (form, pendingComments) {

    var form = document.querySelector('form[data-hubbub]');
    form.addEventListener('submit', function (evt) {
      evt.preventDefault();
      var comment = form.querySelector('[name=comment]').value;
      var name = form.querySelector('[name=name]').value;

      var xmlhttp = new XMLHttpRequest();
      // TODO: Make this configurable!
      xmlhttp.open("POST","https://hubbub.herokuapp.com/api/default/comments",true);
      xmlhttp.setRequestHeader("Content-type", "application/json");

      xmlhttp.onload = function (e) {
        if (xmlhttp.readyState === 4) {
          if (xmlhttp.status >= 200 && xmlhttp.status < 300) {
            var response = JSON.parse(xmlhttp.responseText);
            var commentsContainer = document.querySelector('[data-hubbub-pendingcomment]');
            if (commentsContainer) {
              var commentEl = document.createElement('div');
              commentEl.innerHTML = response.html;
              commentsContainer.appendChild(commentEl);
            }
            alert("Comment sent!");
            form.querySelector('[name=comment]').value = "";
          } else {
            alert("Failed to send comment: " + xmlhttp.statusText);
          }
        }
      };
      xmlhttp.onerror = function (e) {
        alert("Failed to send comment: " + xmlhttp.statusText);
      };

      // TOOD: Get post path from canonical meta tag if it's present
      xmlhttp.send(JSON.stringify({metadata: {name: name}, comment: comment, post: window.location.pathname}));
    });
  }

  hubbub.defaults = defaults;
  hubbub.sendComment = sendComment;
  hubbub.sendForm = sendForm;

})(window.hubbub = {});
<commit_msg>Removed unused code<commit_after>// HubBub client code
// From: https://github.com/almost/hubbub/
// Copyright: Thomas Parslow 2014 (tom@almostobsolete.net)
// License: MIT

(function (hubbub) {
  "use strict";

  var defaults = {
    post: window.location.pathname
  };

  // Send a comment, reports success or failure to the callbacks
  function sendComment(options,  success, failure) {
    var endpoint = options.endpoint || defaults.endpoint,
        comment = options.comment || defaults.comment,
        metadata = options.metadata || defaults.metadata,
        post = options.post || defaults.post;

    var xmlhttp = new XMLHttpRequest();
    // TODO: Make this configurable!
    xmlhttp.open("POST", endpoint, true);
    xmlhttp.setRequestHeader("Content-type", "application/json");

    xmlhttp.onload = function (e) {
      if (xmlhttp.readyState === 4) {
        if (xmlhttp.status >= 200 && xmlhttp.status < 300) {
          var response = JSON.parse(xmlhttp.responseText);
          if (success) success(response);
        } else {
          if (failure) failure(xmlhttp);
        }
      }
    };

    xmlhttp.onerror = function (e) {
      failure(xmlhttp, e);
    };

    xmlhttp.send(JSON.stringify({metadata: metadata, comment: comment, post: post}));
  }

  // Send a comment given in the fields of a form in the DOM
  function sendForm(form, success, failure) {
    var metadata = {}, match;

    for (var i = 0; i < form.length; i++) {
      match = /^metadata_(.*)/.exec(form[i].name);
      if (match) {
        metadata[match[1]] = form[i].value;
      }
    }

    sendComment({endpoint: form.action, comment: form.comment.value, metadata: metadata}, success, failure);
  }

  // Trap all submit events and check for a data-hubbub attribute, if
  // one exists then send a comment from the form.
  function onSubmit (evt) {
    var form = evt.target;
    if (!form.getAttribute('data-hubbub')) {
      // These aren't the forms you're looking for
      return;
    }
    var previewContainer = document.querySelector(evt.target.getAttribute('data-hubbub'));
    evt.preventDefault();

    if (!form.comment) {
      // If there's no comment then just ignore the submit
      return;
    }

    // Add status class while we send
    form.className = form.className + " hubbub-sending";

    sendForm(form, success, failure);

    function removeClass() {
      form.className = form.className.split(' ').filter(function (cls) {
        return cls !== 'hubbub-sending';
      })
    }

    function success(response) {
      removeClass();
      // Clear the comment field
      form.comment.value = '';
      if (previewContainer) {
        var commentEl = document.createElement('div');
        commentEl.className = "hubbub-pending hubbub-added";
        commentEl.innerHTML = response.html;
        previewContainer.appendChild(commentEl);

        // Remove the hubbub-added class to allow CSS transitions to
        // work
        setTimeout(function () {
          commentEl.className = "hubbub-pending";
        }, 100);
      }
    }

    function failure(xmlhttp) {
      removeClass();
      alert("Failed to send comment.");
    }
  }

  document.addEventListener('submit', onSubmit);

  hubbub.defaults = defaults;
  hubbub.sendComment = sendComment;
  hubbub.sendForm = sendForm;

})(window.hubbub = {});
<|endoftext|>