<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const { RawSource } = require("webpack-sources");

const { edit, add } = require("@webassemblyjs/wasm-edit");
const { decode } = require("@webassemblyjs/wasm-parser");
const t = require("@webassemblyjs/ast");

// FIXME(sven): remove this once we're ready to merge
function debug(...msg) {
	// console.log(...msg);
}

function compose(...fns) {
	return fns.reverse().reduce((prevFn, nextFn) => {
		return value => nextFn(prevFn(value));
	}, value => value);
}

// Utility functions
const isGlobalImport = moduleImport => moduleImport.descr.type === "GlobalType";
const initFuncId = t.identifier("__init__");

/**
 * Removes the start instruction
 *
 * @param {ArrayBuffer} state - unused state
 * @returns {ArrayBuffer} bin'
 */
const removeStartFunc = state => bin => {
	debug("removeStartFunc");

	return edit(bin, {
		Start(path) {
			path.remove();
		}
	});
};

function getStartFuncIndex(ast) {
	let startAtFuncIndex;

	t.traverse(ast, {
		Start(path) {
			startAtFuncIndex = path.node.index;
		}
	});

	return startAtFuncIndex;
}

function getImportedGlobals(ast) {
	const importedGlobals = [];

	t.traverse(ast, {
		ModuleImport({ node }) {
			if (isGlobalImport(node) === true) {
				importedGlobals.push(node);
			}
		}
	});

	return importedGlobals;
}

/**
 * Rewrite the import globals:
 * - removes the ModuleImport instruction
 * - injects at the same offset a mutable global of the same time
 *
 * Since the imported globals are before the other global declarations, our
 * indices will be preserved.
 *
 * Note that globals will become mutable.
 *
 * @param {ArrayBuffer} bin - the input wasm binary
 * @returns {ArrayBuffer} bin'
 */
const rewriteImportedGlobals = state => bin => {
	debug("rewriteImportedGlobals");

	const newGlobals = [];

	bin = edit(bin, {
		ModuleImport(path) {
			if (isGlobalImport(path.node) === true) {
				const globalType = path.node.descr;

				globalType.mutability = "var";

				newGlobals.push(
					t.global(globalType, [
						t.objectInstruction("const", "i32", [t.numberLiteral(0)])
					])
				);

				debug("remove import", path.node.module, path.node.name);
				path.remove();
			}
		}
	});

	// Add global declaration instructions
	return add(bin, newGlobals);
};

/**
 * Add an init function.
 *
 * The init function fills the globals given input arguments.
 *
 * @param {ArrayBuffer} bin - the input wasm binary
 * @returns {ArrayBuffer} bin'
 */
const addInitFunction = ({
	startAtFuncIndex,
	importedGlobals,
	funcSectionMetadata
}) => bin => {
	debug("addInitFunction");

	const nextTypeIndex = funcSectionMetadata.vectorOfSize;

	const funcParams = importedGlobals.map(importedGlobal => {
		// used for debugging
		const id = t.identifier(`${importedGlobal.module}.${importedGlobal.name}`);

		return t.funcParam(importedGlobal.descr.valtype, id);
	});

	const funcBody = importedGlobals.reduce((acc, importedGlobal, index) => {
		const args = [t.indexLiteral(index)];
		const body = [
			t.instruction("get_local", args),
			t.instruction("set_global", args)
		];

		return [...acc, ...body];
	}, []);

	if (typeof startAtFuncIndex !== "undefined") {
		debug("call start func", startAtFuncIndex.value);

		funcBody.push(t.callInstruction(startAtFuncIndex));
	}

	const funcResults = [];

	const func = t.func(initFuncId, funcParams, funcResults, funcBody);

	const functype = t.typeInstructionFunc(func.params, func.result);
	const funcindex = t.indexInFuncSection(t.indexLiteral(nextTypeIndex));

	const moduleExport = t.moduleExport(
		initFuncId.value,
		"Func",
		t.indexLiteral(nextTypeIndex)
	);

	return add(bin, [func, moduleExport, funcindex, functype]);
};

class WebAssemblyGenerator {
	generate(module) {
		const bin = module.originalSource().source();

		const ast = decode(bin, {
			ignoreDataSection: true
		});

		const importedGlobals = getImportedGlobals(ast);
		const funcSectionMetadata = t.getSectionMetadata(ast, "func");
		const startAtFuncIndex = getStartFuncIndex(ast);

		const transform = compose(
			removeStartFunc(),

			rewriteImportedGlobals(),

			addInitFunction({
				importedGlobals,
				funcSectionMetadata,
				startAtFuncIndex
			})
		);

		debug("__________________________________________________________");
		const newBin = transform(bin);
		debug("__________________________________________________________");

		// console.log(require("@webassemblyjs/wast-printer").print(decode(newBin)));

		return new RawSource(newBin);
	}
}

module.exports = WebAssemblyGenerator;
<commit_msg>style: few jsdoc fixes<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const { RawSource } = require("webpack-sources");

const { edit, add } = require("@webassemblyjs/wasm-edit");
const { decode } = require("@webassemblyjs/wasm-parser");
const t = require("@webassemblyjs/ast");

// FIXME(sven): remove this once we're ready to merge
function debug(...msg) {
	// console.log(...msg);
}

function compose(...fns) {
	return fns.reverse().reduce((prevFn, nextFn) => {
		return value => nextFn(prevFn(value));
	}, value => value);
}

// Utility functions
const isGlobalImport = moduleImport => moduleImport.descr.type === "GlobalType";
const initFuncId = t.identifier("__init__");

/**
 * Removes the start instruction
 *
 * @param {Object} state - unused state
 * @returns {ArrayBuffer} bin'
 */
const removeStartFunc = state => bin => {
	debug("removeStartFunc");

	return edit(bin, {
		Start(path) {
			path.remove();
		}
	});
};

function getStartFuncIndex(ast) {
	let startAtFuncIndex;

	t.traverse(ast, {
		Start(path) {
			startAtFuncIndex = path.node.index;
		}
	});

	return startAtFuncIndex;
}

function getImportedGlobals(ast) {
	const importedGlobals = [];

	t.traverse(ast, {
		ModuleImport({ node }) {
			if (isGlobalImport(node) === true) {
				importedGlobals.push(node);
			}
		}
	});

	return importedGlobals;
}

/**
 * Rewrite the import globals:
 * - removes the ModuleImport instruction
 * - injects at the same offset a mutable global of the same time
 *
 * Since the imported globals are before the other global declarations, our
 * indices will be preserved.
 *
 * Note that globals will become mutable.
 *
 * @param {Object} state - unused state
 * @returns {ArrayBuffer} bin'
 */
const rewriteImportedGlobals = state => bin => {
	debug("rewriteImportedGlobals");

	const newGlobals = [];

	bin = edit(bin, {
		ModuleImport(path) {
			if (isGlobalImport(path.node) === true) {
				const globalType = path.node.descr;

				globalType.mutability = "var";

				newGlobals.push(
					t.global(globalType, [
						t.objectInstruction("const", "i32", [t.numberLiteral(0)])
					])
				);

				debug("remove import", path.node.module, path.node.name);
				path.remove();
			}
		}
	});

	// Add global declaration instructions
	return add(bin, newGlobals);
};

/**
 * Add an init function.
 *
 * The init function fills the globals given input arguments.
 *
 * @param {Object} state - transformation state
 * @returns {ArrayBuffer} bin'
 */
const addInitFunction = ({
	startAtFuncIndex,
	importedGlobals,
	funcSectionMetadata
}) => bin => {
	debug("addInitFunction");

	const nextTypeIndex = funcSectionMetadata.vectorOfSize;

	const funcParams = importedGlobals.map(importedGlobal => {
		// used for debugging
		const id = t.identifier(`${importedGlobal.module}.${importedGlobal.name}`);

		return t.funcParam(importedGlobal.descr.valtype, id);
	});

	const funcBody = importedGlobals.reduce((acc, importedGlobal, index) => {
		const args = [t.indexLiteral(index)];
		const body = [
			t.instruction("get_local", args),
			t.instruction("set_global", args)
		];

		return [...acc, ...body];
	}, []);

	if (typeof startAtFuncIndex !== "undefined") {
		debug("call start func", startAtFuncIndex.value);

		funcBody.push(t.callInstruction(startAtFuncIndex));
	}

	const funcResults = [];

	const func = t.func(initFuncId, funcParams, funcResults, funcBody);

	const functype = t.typeInstructionFunc(func.params, func.result);
	const funcindex = t.indexInFuncSection(t.indexLiteral(nextTypeIndex));

	const moduleExport = t.moduleExport(
		initFuncId.value,
		"Func",
		t.indexLiteral(nextTypeIndex)
	);

	return add(bin, [func, moduleExport, funcindex, functype]);
};

class WebAssemblyGenerator {
	generate(module) {
		const bin = module.originalSource().source();

		const ast = decode(bin, {
			ignoreDataSection: true
		});

		const importedGlobals = getImportedGlobals(ast);
		const funcSectionMetadata = t.getSectionMetadata(ast, "func");
		const startAtFuncIndex = getStartFuncIndex(ast);

		const transform = compose(
			removeStartFunc(),

			rewriteImportedGlobals(),

			addInitFunction({
				importedGlobals,
				funcSectionMetadata,
				startAtFuncIndex
			})
		);

		debug("__________________________________________________________");
		const newBin = transform(bin);
		debug("__________________________________________________________");

		// console.log(require("@webassemblyjs/wast-printer").print(decode(newBin)));

		return new RawSource(newBin);
	}
}

module.exports = WebAssemblyGenerator;
<|endoftext|>


<commit_before><commit_msg>Disabled google plus sharing<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

<include src="../uber/uber_utils.js"></include>
<include src="extension_commands_overlay.js"></include>
<include src="extension_focus_manager.js"></include>
<include src="extension_list.js"></include>
<include src="pack_extension_overlay.js"></include>

<if expr="pp_ifdef('chromeos')">
<include src="chromeos/kiosk_apps.js"></include>
</if>

// Used for observing function of the backend datasource for this page by
// tests.
var webuiResponded = false;

cr.define('extensions', function() {
  var ExtensionsList = options.ExtensionsList;

  // Implements the DragWrapper handler interface.
  var dragWrapperHandler = {
    /** @override */
    shouldAcceptDrag: function(e) {
      // We can't access filenames during the 'dragenter' event, so we have to
      // wait until 'drop' to decide whether to do something with the file or
      // not.
      // See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p
      return (e.dataTransfer.types &&
              e.dataTransfer.types.indexOf('Files') > -1);
    },
    /** @override */
    doDragEnter: function() {
      chrome.send('startDrag');
      ExtensionSettings.showOverlay(null);
      ExtensionSettings.showOverlay($('dropTargetOverlay'));
    },
    /** @override */
    doDragLeave: function() {
      ExtensionSettings.showOverlay(null);
      chrome.send('stopDrag');
    },
    /** @override */
    doDragOver: function(e) {
      e.preventDefault();
    },
    /** @override */
    doDrop: function(e) {
      ExtensionSettings.showOverlay(null);
      if (e.dataTransfer.files.length != 1)
        return;

      var toSend = null;
      // Files lack a check if they're a directory, but we can find out through
      // its item entry.
      var fileIndex = e.dataTransfer.types.indexOf('Files');
      if (e.dataTransfer.items[fileIndex].webkitGetAsEntry().isDirectory)
        toSend = 'installDroppedDirectory';
      // Only process files that look like extensions. Other files should
      // navigate the browser normally.
      else if (/\.(crx|user\.js)$/i.test(e.dataTransfer.files[0].name))
        toSend = 'installDroppedFile';

      if (toSend) {
        e.preventDefault();
        chrome.send(toSend);
      }
    }
  };

  /**
   * ExtensionSettings class
   * @class
   */
  function ExtensionSettings() {}

  cr.addSingletonGetter(ExtensionSettings);

  ExtensionSettings.prototype = {
    __proto__: HTMLDivElement.prototype,

    /**
     * Perform initial setup.
     */
    initialize: function() {
      uber.onContentFrameLoaded();

      measureCheckboxStrings();

      // Set the title.
      var title = loadTimeData.getString('extensionSettings');
      uber.invokeMethodOnParent('setTitle', {title: title});

      // This will request the data to show on the page and will get a response
      // back in returnExtensionsData.
      chrome.send('extensionSettingsRequestExtensionsData');

      $('toggle-dev-on').addEventListener('change',
          this.handleToggleDevMode_.bind(this));
      $('dev-controls').addEventListener('webkitTransitionEnd',
          this.handleDevControlsTransitionEnd_.bind(this));

      // Set up the three dev mode buttons (load unpacked, pack and update).
      $('load-unpacked').addEventListener('click',
          this.handleLoadUnpackedExtension_.bind(this));
      $('pack-extension').addEventListener('click',
          this.handlePackExtension_.bind(this));
      $('update-extensions-now').addEventListener('click',
          this.handleUpdateExtensionNow_.bind(this));

      if (!loadTimeData.getBoolean('offStoreInstallEnabled')) {
        this.dragWrapper_ = new cr.ui.DragWrapper(document.documentElement,
                                                  dragWrapperHandler);
      }

      var packExtensionOverlay = extensions.PackExtensionOverlay.getInstance();
      packExtensionOverlay.initializePage();

      // Hook up the configure commands link to the overlay.
      var link = document.querySelector('.extension-commands-config');
      link.addEventListener('click',
          this.handleExtensionCommandsConfig_.bind(this));

      // Initialize the Commands overlay.
      var extensionCommandsOverlay =
          extensions.ExtensionCommandsOverlay.getInstance();
      extensionCommandsOverlay.initializePage();

      // Initialize the kiosk overlay.
      if (cr.isChromeOS) {
        var kioskOverlay = extensions.KioskAppsOverlay.getInstance();
        kioskOverlay.initialize();

        $('add-kiosk-app').addEventListener('click', function() {
          ExtensionSettings.showOverlay($('kiosk-apps-page'));
          kioskOverlay.didShowPage();
        });

        extensions.KioskDisableBailoutConfirm.getInstance().initialize();
      }

      cr.ui.overlay.setupOverlay($('dropTargetOverlay'));
      cr.ui.overlay.globalInitialization();

      extensions.ExtensionFocusManager.getInstance().initialize();

      var path = document.location.pathname;
      if (path.length > 1) {
        // Skip starting slash and remove trailing slash (if any).
        var overlayName = path.slice(1).replace(/\/$/, '');
        if (overlayName == 'configureCommands')
          this.showExtensionCommandsConfigUi_();
      }

      preventDefaultOnPoundLinkClicks();  // From webui/js/util.js.
    },

    /**
     * Handles the Load Unpacked Extension button.
     * @param {Event} e Change event.
     * @private
     */
    handleLoadUnpackedExtension_: function(e) {
      chrome.send('extensionSettingsLoadUnpackedExtension');
    },

    /**
     * Handles the Pack Extension button.
     * @param {Event} e Change event.
     * @private
     */
    handlePackExtension_: function(e) {
      ExtensionSettings.showOverlay($('packExtensionOverlay'));
      chrome.send('metricsHandler:recordAction', ['Options_PackExtension']);
    },

    /**
     * Shows the Extension Commands configuration UI.
     * @param {Event} e Change event.
     * @private
     */
    showExtensionCommandsConfigUi_: function(e) {
      ExtensionSettings.showOverlay($('extensionCommandsOverlay'));
      chrome.send('metricsHandler:recordAction',
                  ['Options_ExtensionCommands']);
    },

    /**
     * Handles the Configure (Extension) Commands link.
     * @param {Event} e Change event.
     * @private
     */
    handleExtensionCommandsConfig_: function(e) {
      this.showExtensionCommandsConfigUi_();
    },

    /**
     * Handles the Update Extension Now button.
     * @param {Event} e Change event.
     * @private
     */
    handleUpdateExtensionNow_: function(e) {
      chrome.send('extensionSettingsAutoupdate');
    },

    /**
     * Handles the Toggle Dev Mode button.
     * @param {Event} e Change event.
     * @private
     */
    handleToggleDevMode_: function(e) {
      if ($('toggle-dev-on').checked) {
        $('dev-controls').hidden = false;
        window.setTimeout(function() {
          $('extension-settings').classList.add('dev-mode');
        }, 0);
      } else {
        $('extension-settings').classList.remove('dev-mode');
      }

      chrome.send('extensionSettingsToggleDeveloperMode');
    },

    /**
     * Called when a transition has ended for #dev-controls.
     * @param {Event} e webkitTransitionEnd event.
     * @private
     */
    handleDevControlsTransitionEnd_: function(e) {
      if (e.propertyName == 'height' &&
          !$('extension-settings').classList.contains('dev-mode')) {
        $('dev-controls').hidden = true;
      }
    },
  };

  /**
   * Called by the dom_ui_ to re-populate the page with data representing
   * the current state of installed extensions.
   */
  ExtensionSettings.returnExtensionsData = function(extensionsData) {
    // We can get called many times in short order, thus we need to
    // be careful to remove the 'finished loading' timeout.
    if (this.loadingTimeout_)
      window.clearTimeout(this.loadingTimeout_);
    document.documentElement.classList.add('loading');
    this.loadingTimeout_ = window.setTimeout(function() {
      document.documentElement.classList.remove('loading');
    }, 0);

    webuiResponded = true;

    if (extensionsData.extensions.length > 0) {
      // Enforce order specified in the data or (if equal) then sort by
      // extension name (case-insensitive).
      extensionsData.extensions.sort(function(a, b) {
        if (a.order == b.order) {
          a = a.name.toLowerCase();
          b = b.name.toLowerCase();
          return a < b ? -1 : (a > b ? 1 : 0);
        } else {
          return a.order < b.order ? -1 : 1;
        }
      });
    }

    var pageDiv = $('extension-settings');
    var marginTop = 0;
    if (extensionsData.profileIsManaged) {
      pageDiv.classList.add('profile-is-managed');
    } else {
      pageDiv.classList.remove('profile-is-managed');
    }
    if (extensionsData.profileIsManaged) {
      pageDiv.classList.add('showing-banner');
      $('toggle-dev-on').disabled = true;
      marginTop += 45;
    } else {
      pageDiv.classList.remove('showing-banner');
      $('toggle-dev-on').disabled = false;
    }

    pageDiv.style.marginTop = marginTop + 'px';

    if (extensionsData.developerMode) {
      pageDiv.classList.add('dev-mode');
      $('toggle-dev-on').checked = true;
      $('dev-controls').hidden = false;
    } else {
      pageDiv.classList.remove('dev-mode');
      $('toggle-dev-on').checked = false;
    }

    $('load-unpacked').disabled = extensionsData.loadUnpackedDisabled;

    ExtensionsList.prototype.data_ = extensionsData;
    var extensionList = $('extension-settings-list');
    ExtensionsList.decorate(extensionList);
  }

  // Indicate that warning |message| has occured for pack of |crx_path| and
  // |pem_path| files.  Ask if user wants override the warning.  Send
  // |overrideFlags| to repeated 'pack' call to accomplish the override.
  ExtensionSettings.askToOverrideWarning =
      function(message, crx_path, pem_path, overrideFlags) {
    var closeAlert = function() {
      ExtensionSettings.showOverlay(null);
    };

    alertOverlay.setValues(
        loadTimeData.getString('packExtensionWarningTitle'),
        message,
        loadTimeData.getString('packExtensionProceedAnyway'),
        loadTimeData.getString('cancel'),
        function() {
          chrome.send('pack', [crx_path, pem_path, overrideFlags]);
          closeAlert();
        },
        closeAlert);
    ExtensionSettings.showOverlay($('alertOverlay'));
  }

  /**
   * Returns the current overlay or null if one does not exist.
   * @return {Element} The overlay element.
   */
  ExtensionSettings.getCurrentOverlay = function() {
    return document.querySelector('#overlay .page.showing');
  }

  /**
   * Sets the given overlay to show. This hides whatever overlay is currently
   * showing, if any.
   * @param {HTMLElement} node The overlay page to show. If falsey, all overlays
   *     are hidden.
   */
  ExtensionSettings.showOverlay = function(node) {
    var currentlyShowingOverlay = ExtensionSettings.getCurrentOverlay();
    if (currentlyShowingOverlay)
      currentlyShowingOverlay.classList.remove('showing');

    if (node)
      node.classList.add('showing');
    overlay.hidden = !node;
    uber.invokeMethodOnParent(node ? 'beginInterceptingEvents' :
                                     'stopInterceptingEvents');
  }

  /**
   * Utility function to find the width of various UI strings and synchronize
   * the width of relevant spans. This is crucial for making sure the
   * Enable/Enabled checkboxes align, as well as the Developer Mode checkbox.
   */
  function measureCheckboxStrings() {
    var trashWidth = 30;
    var measuringDiv = $('font-measuring-div');
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsEnabled');
    var pxWidth = measuringDiv.clientWidth + trashWidth;
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsEnable');
    pxWidth = Math.max(measuringDiv.clientWidth + trashWidth, pxWidth);
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsDeveloperMode');
    pxWidth = Math.max(measuringDiv.clientWidth, pxWidth);

    var style = document.createElement('style');
    style.type = 'text/css';
    style.textContent =
        '.enable-checkbox-text {' +
        '  min-width: ' + (pxWidth - trashWidth) + 'px;' +
        '}' +
        '#dev-toggle span {' +
        '  min-width: ' + pxWidth + 'px;' +
        '}';
    document.querySelector('head').appendChild(style);
  }

  // Export
  return {
    ExtensionSettings: ExtensionSettings
  };
});

var ExtensionSettings = extensions.ExtensionSettings;

window.addEventListener('load', function(e) {
  ExtensionSettings.getInstance().initialize();
});
<commit_msg>Fix drag and drop from Chrome OS Files.app to the extension page.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

<include src="../uber/uber_utils.js"></include>
<include src="extension_commands_overlay.js"></include>
<include src="extension_focus_manager.js"></include>
<include src="extension_list.js"></include>
<include src="pack_extension_overlay.js"></include>

<if expr="pp_ifdef('chromeos')">
<include src="chromeos/kiosk_apps.js"></include>
</if>

// Used for observing function of the backend datasource for this page by
// tests.
var webuiResponded = false;

cr.define('extensions', function() {
  var ExtensionsList = options.ExtensionsList;

  // Implements the DragWrapper handler interface.
  var dragWrapperHandler = {
    /** @override */
    shouldAcceptDrag: function(e) {
      // We can't access filenames during the 'dragenter' event, so we have to
      // wait until 'drop' to decide whether to do something with the file or
      // not.
      // See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p
      return (e.dataTransfer.types &&
              e.dataTransfer.types.indexOf('Files') > -1);
    },
    /** @override */
    doDragEnter: function() {
      chrome.send('startDrag');
      ExtensionSettings.showOverlay(null);
      ExtensionSettings.showOverlay($('dropTargetOverlay'));
    },
    /** @override */
    doDragLeave: function() {
      ExtensionSettings.showOverlay(null);
      chrome.send('stopDrag');
    },
    /** @override */
    doDragOver: function(e) {
      e.preventDefault();
    },
    /** @override */
    doDrop: function(e) {
      ExtensionSettings.showOverlay(null);
      if (e.dataTransfer.files.length != 1)
        return;

      var toSend = null;
      // Files lack a check if they're a directory, but we can find out through
      // its item entry.
      for (var i = 0; i < e.dataTransfer.items.length; ++i) {
        if (e.dataTransfer.items[i].kind == 'file' &&
            e.dataTransfer.items[i].webkitGetAsEntry().isDirectory) {
          toSend = 'installDroppedDirectory';
          break;
        }
      }
      // Only process files that look like extensions. Other files should
      // navigate the browser normally.
      if (!toSend && /\.(crx|user\.js)$/i.test(e.dataTransfer.files[0].name))
        toSend = 'installDroppedFile';

      if (toSend) {
        e.preventDefault();
        chrome.send(toSend);
      }
    }
  };

  /**
   * ExtensionSettings class
   * @class
   */
  function ExtensionSettings() {}

  cr.addSingletonGetter(ExtensionSettings);

  ExtensionSettings.prototype = {
    __proto__: HTMLDivElement.prototype,

    /**
     * Perform initial setup.
     */
    initialize: function() {
      uber.onContentFrameLoaded();

      measureCheckboxStrings();

      // Set the title.
      var title = loadTimeData.getString('extensionSettings');
      uber.invokeMethodOnParent('setTitle', {title: title});

      // This will request the data to show on the page and will get a response
      // back in returnExtensionsData.
      chrome.send('extensionSettingsRequestExtensionsData');

      $('toggle-dev-on').addEventListener('change',
          this.handleToggleDevMode_.bind(this));
      $('dev-controls').addEventListener('webkitTransitionEnd',
          this.handleDevControlsTransitionEnd_.bind(this));

      // Set up the three dev mode buttons (load unpacked, pack and update).
      $('load-unpacked').addEventListener('click',
          this.handleLoadUnpackedExtension_.bind(this));
      $('pack-extension').addEventListener('click',
          this.handlePackExtension_.bind(this));
      $('update-extensions-now').addEventListener('click',
          this.handleUpdateExtensionNow_.bind(this));

      if (!loadTimeData.getBoolean('offStoreInstallEnabled')) {
        this.dragWrapper_ = new cr.ui.DragWrapper(document.documentElement,
                                                  dragWrapperHandler);
      }

      var packExtensionOverlay = extensions.PackExtensionOverlay.getInstance();
      packExtensionOverlay.initializePage();

      // Hook up the configure commands link to the overlay.
      var link = document.querySelector('.extension-commands-config');
      link.addEventListener('click',
          this.handleExtensionCommandsConfig_.bind(this));

      // Initialize the Commands overlay.
      var extensionCommandsOverlay =
          extensions.ExtensionCommandsOverlay.getInstance();
      extensionCommandsOverlay.initializePage();

      // Initialize the kiosk overlay.
      if (cr.isChromeOS) {
        var kioskOverlay = extensions.KioskAppsOverlay.getInstance();
        kioskOverlay.initialize();

        $('add-kiosk-app').addEventListener('click', function() {
          ExtensionSettings.showOverlay($('kiosk-apps-page'));
          kioskOverlay.didShowPage();
        });

        extensions.KioskDisableBailoutConfirm.getInstance().initialize();
      }

      cr.ui.overlay.setupOverlay($('dropTargetOverlay'));
      cr.ui.overlay.globalInitialization();

      extensions.ExtensionFocusManager.getInstance().initialize();

      var path = document.location.pathname;
      if (path.length > 1) {
        // Skip starting slash and remove trailing slash (if any).
        var overlayName = path.slice(1).replace(/\/$/, '');
        if (overlayName == 'configureCommands')
          this.showExtensionCommandsConfigUi_();
      }

      preventDefaultOnPoundLinkClicks();  // From webui/js/util.js.
    },

    /**
     * Handles the Load Unpacked Extension button.
     * @param {Event} e Change event.
     * @private
     */
    handleLoadUnpackedExtension_: function(e) {
      chrome.send('extensionSettingsLoadUnpackedExtension');
    },

    /**
     * Handles the Pack Extension button.
     * @param {Event} e Change event.
     * @private
     */
    handlePackExtension_: function(e) {
      ExtensionSettings.showOverlay($('packExtensionOverlay'));
      chrome.send('metricsHandler:recordAction', ['Options_PackExtension']);
    },

    /**
     * Shows the Extension Commands configuration UI.
     * @param {Event} e Change event.
     * @private
     */
    showExtensionCommandsConfigUi_: function(e) {
      ExtensionSettings.showOverlay($('extensionCommandsOverlay'));
      chrome.send('metricsHandler:recordAction',
                  ['Options_ExtensionCommands']);
    },

    /**
     * Handles the Configure (Extension) Commands link.
     * @param {Event} e Change event.
     * @private
     */
    handleExtensionCommandsConfig_: function(e) {
      this.showExtensionCommandsConfigUi_();
    },

    /**
     * Handles the Update Extension Now button.
     * @param {Event} e Change event.
     * @private
     */
    handleUpdateExtensionNow_: function(e) {
      chrome.send('extensionSettingsAutoupdate');
    },

    /**
     * Handles the Toggle Dev Mode button.
     * @param {Event} e Change event.
     * @private
     */
    handleToggleDevMode_: function(e) {
      if ($('toggle-dev-on').checked) {
        $('dev-controls').hidden = false;
        window.setTimeout(function() {
          $('extension-settings').classList.add('dev-mode');
        }, 0);
      } else {
        $('extension-settings').classList.remove('dev-mode');
      }

      chrome.send('extensionSettingsToggleDeveloperMode');
    },

    /**
     * Called when a transition has ended for #dev-controls.
     * @param {Event} e webkitTransitionEnd event.
     * @private
     */
    handleDevControlsTransitionEnd_: function(e) {
      if (e.propertyName == 'height' &&
          !$('extension-settings').classList.contains('dev-mode')) {
        $('dev-controls').hidden = true;
      }
    },
  };

  /**
   * Called by the dom_ui_ to re-populate the page with data representing
   * the current state of installed extensions.
   */
  ExtensionSettings.returnExtensionsData = function(extensionsData) {
    // We can get called many times in short order, thus we need to
    // be careful to remove the 'finished loading' timeout.
    if (this.loadingTimeout_)
      window.clearTimeout(this.loadingTimeout_);
    document.documentElement.classList.add('loading');
    this.loadingTimeout_ = window.setTimeout(function() {
      document.documentElement.classList.remove('loading');
    }, 0);

    webuiResponded = true;

    if (extensionsData.extensions.length > 0) {
      // Enforce order specified in the data or (if equal) then sort by
      // extension name (case-insensitive).
      extensionsData.extensions.sort(function(a, b) {
        if (a.order == b.order) {
          a = a.name.toLowerCase();
          b = b.name.toLowerCase();
          return a < b ? -1 : (a > b ? 1 : 0);
        } else {
          return a.order < b.order ? -1 : 1;
        }
      });
    }

    var pageDiv = $('extension-settings');
    var marginTop = 0;
    if (extensionsData.profileIsManaged) {
      pageDiv.classList.add('profile-is-managed');
    } else {
      pageDiv.classList.remove('profile-is-managed');
    }
    if (extensionsData.profileIsManaged) {
      pageDiv.classList.add('showing-banner');
      $('toggle-dev-on').disabled = true;
      marginTop += 45;
    } else {
      pageDiv.classList.remove('showing-banner');
      $('toggle-dev-on').disabled = false;
    }

    pageDiv.style.marginTop = marginTop + 'px';

    if (extensionsData.developerMode) {
      pageDiv.classList.add('dev-mode');
      $('toggle-dev-on').checked = true;
      $('dev-controls').hidden = false;
    } else {
      pageDiv.classList.remove('dev-mode');
      $('toggle-dev-on').checked = false;
    }

    $('load-unpacked').disabled = extensionsData.loadUnpackedDisabled;

    ExtensionsList.prototype.data_ = extensionsData;
    var extensionList = $('extension-settings-list');
    ExtensionsList.decorate(extensionList);
  }

  // Indicate that warning |message| has occured for pack of |crx_path| and
  // |pem_path| files.  Ask if user wants override the warning.  Send
  // |overrideFlags| to repeated 'pack' call to accomplish the override.
  ExtensionSettings.askToOverrideWarning =
      function(message, crx_path, pem_path, overrideFlags) {
    var closeAlert = function() {
      ExtensionSettings.showOverlay(null);
    };

    alertOverlay.setValues(
        loadTimeData.getString('packExtensionWarningTitle'),
        message,
        loadTimeData.getString('packExtensionProceedAnyway'),
        loadTimeData.getString('cancel'),
        function() {
          chrome.send('pack', [crx_path, pem_path, overrideFlags]);
          closeAlert();
        },
        closeAlert);
    ExtensionSettings.showOverlay($('alertOverlay'));
  }

  /**
   * Returns the current overlay or null if one does not exist.
   * @return {Element} The overlay element.
   */
  ExtensionSettings.getCurrentOverlay = function() {
    return document.querySelector('#overlay .page.showing');
  }

  /**
   * Sets the given overlay to show. This hides whatever overlay is currently
   * showing, if any.
   * @param {HTMLElement} node The overlay page to show. If falsey, all overlays
   *     are hidden.
   */
  ExtensionSettings.showOverlay = function(node) {
    var currentlyShowingOverlay = ExtensionSettings.getCurrentOverlay();
    if (currentlyShowingOverlay)
      currentlyShowingOverlay.classList.remove('showing');

    if (node)
      node.classList.add('showing');
    overlay.hidden = !node;
    uber.invokeMethodOnParent(node ? 'beginInterceptingEvents' :
                                     'stopInterceptingEvents');
  }

  /**
   * Utility function to find the width of various UI strings and synchronize
   * the width of relevant spans. This is crucial for making sure the
   * Enable/Enabled checkboxes align, as well as the Developer Mode checkbox.
   */
  function measureCheckboxStrings() {
    var trashWidth = 30;
    var measuringDiv = $('font-measuring-div');
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsEnabled');
    var pxWidth = measuringDiv.clientWidth + trashWidth;
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsEnable');
    pxWidth = Math.max(measuringDiv.clientWidth + trashWidth, pxWidth);
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsDeveloperMode');
    pxWidth = Math.max(measuringDiv.clientWidth, pxWidth);

    var style = document.createElement('style');
    style.type = 'text/css';
    style.textContent =
        '.enable-checkbox-text {' +
        '  min-width: ' + (pxWidth - trashWidth) + 'px;' +
        '}' +
        '#dev-toggle span {' +
        '  min-width: ' + pxWidth + 'px;' +
        '}';
    document.querySelector('head').appendChild(style);
  }

  // Export
  return {
    ExtensionSettings: ExtensionSettings
  };
});

var ExtensionSettings = extensions.ExtensionSettings;

window.addEventListener('load', function(e) {
  ExtensionSettings.getInstance().initialize();
});
<|endoftext|>


<commit_before>'use strict';

const async = require('async');
const wd = require('wd');

const config = {
  host: 'ondemand.saucelabs.com',
  port: 80,
  username: process.env.SAUCE_USER,
  accessKey: process.env.SAUCE_ACCESS_KEY,
};

const isAdminRunner = process.argv[2] === 'admin';

let allTestsPassed = true;
// overwrite the default exit code
// in case not all worker can be run (due to saucelabs limits),
// `queue.drain` below will not be called
// and the script would silently exit with error code 0
process.exitCode = 2;
process.on('exit', (code) => {
  if (code === 2) {
    console.log('\x1B[31mFAILED\x1B[39m Not all saucelabs runner have been started.');
  }
});

const sauceTestWorker = async.queue((testSettings, callback) => {
  const browser = wd.promiseChainRemote(
      config.host, config.port, config.username, config.accessKey);
  const name = [process.env.GIT_HASH].concat(process.env.SAUCE_NAME || []).concat([
    `${testSettings.browserName} ${testSettings.version}, ${testSettings.platform}`,
  ]).join(' - ');
  testSettings.name = name;
  testSettings.public = true;
  testSettings.build = process.env.GIT_HASH;
  // console.json can be downloaded via saucelabs,
  // don't know how to print them into output of the tests
  testSettings.extendedDebugging = true;
  testSettings.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;

  browser.init(testSettings).get('http://localhost:9001/tests/frontend/', () => {
    const url = `https://saucelabs.com/jobs/${browser.sessionID}`;
    console.log(`Remote sauce test '${name}' started! ${url}`);

    // tear down the test excecution
    const stopSauce = (success, timesup) => {
      clearInterval(getStatusInterval);
      clearTimeout(timeout);

      browser.quit(() => {
        if (!success) {
          allTestsPassed = false;
        }

        // if stopSauce is called via timeout
        // (in contrast to via getStatusInterval) than the log of up to the last
        // five seconds may not be available here. It's an error anyway, so don't care about it.
        printLog(logIndex);

        if (timesup) {
          console.log(`[${testSettings.browserName} ${testSettings.platform}` +
            `${testSettings.version === '' ? '' : (` ${testSettings.version}`)}]` +
            ' \x1B[31mFAILED\x1B[39m allowed test duration exceeded');
        }
        console.log(`Remote sauce test '${name}' finished! ${url}`);

        callback();
      });
    };

    /**
       * timeout if a test hangs or the job exceeds 14.5 minutes
       * It's necessary because if travis kills the saucelabs session due to inactivity,
       * we don't get any output
       * @todo this should be configured in testSettings, see
       * https://wiki.saucelabs.com/display/DOCS/Test+Configuration+Options#TestConfigurationOptions-Timeouts
       */
    const timeout = setTimeout(() => {
      stopSauce(false, true);
    }, 870000); // travis timeout is 15 minutes, set this to a slightly lower value

    let knownConsoleText = '';
    // how many characters of the log have been sent to travis
    let logIndex = 0;
    const getStatusInterval = setInterval(() => {
      browser.eval("$('#console').text()", (err, consoleText) => {
        if (!consoleText || err) {
          return;
        }
        knownConsoleText = consoleText;

        if (knownConsoleText.indexOf('FINISHED') > 0) {
          const match = knownConsoleText.match(
              /FINISHED.*([0-9]+) tests passed, ([0-9]+) tests failed/);
          // finished without failures
          if (match[2] && match[2] === '0') {
            stopSauce(true);

            // finished but some tests did not return or some tests failed
          } else {
            stopSauce(false);
          }
        } else {
          // not finished yet
          printLog(logIndex);
          logIndex = knownConsoleText.length;
        }
      });
    }, 5000);

    /**
       * Replaces color codes in the test runners log, appends
       * browser name, platform etc. to every line and prints them.
       *
       * @param {number} index offset from where to start
       */
    const printLog = (index) => {
      let testResult = knownConsoleText.substring(index)
          .replace(/\[red\]/g, '\x1B[31m').replace(/\[yellow\]/g, '\x1B[33m')
          .replace(/\[green\]/g, '\x1B[32m').replace(/\[clear\]/g, '\x1B[39m');
      testResult = testResult.split('\\n').map((line) => `[${testSettings.browserName} ` +
        `${testSettings.platform}` +
        `${testSettings.version === '' ? '' : (` ${testSettings.version}`)}]` +
        `${line}`).join('\n');

      console.log(testResult);
    };
  });
}, 6); // run 6 tests in parrallel

if (!isAdminRunner) {
  // 1) Firefox on Linux
  sauceTestWorker.push({
    platform: 'Windows 10',
    browserName: 'firefox',
    version: '84.0',
  });

  // 2) Chrome on Linux
  sauceTestWorker.push({
    platform: 'Windows 7',
    browserName: 'chrome',
    version: '55.0',
    args: ['--use-fake-device-for-media-stream'],
  });

  /*
  // 3) Safari on OSX 10.15
  sauceTestWorker.push({
      'platform'       : 'OS X 10.15'
    , 'browserName'    : 'safari'
    , 'version'        : '13.1'
  });
  */

  // 4) Safari on OSX 10.14
  sauceTestWorker.push({
    platform: 'OS X 10.15',
    browserName: 'safari',
    version: '13.1',
  });
  // IE 10 doesn't appear to be working anyway
  /*
  // 4) IE 10 on Win 8
  sauceTestWorker.push({
      'platform'       : 'Windows 8'
    , 'browserName'    : 'iexplore'
    , 'version'        : '10.0'
  });
  */
  // 5) Edge on Win 10
  sauceTestWorker.push({
    platform: 'Windows 10',
    browserName: 'microsoftedge',
    version: '83.0',
  });
  // 6) Firefox on Win 7
  sauceTestWorker.push({
    platform: 'Windows 7',
    browserName: 'firefox',
    version: '78.0',
  });
} else {
  // 4) Safari on OSX 10.14
  sauceTestWorker.push({
    platform: 'OS X 10.15',
    browserName: 'safari',
    version: '13.1',
  });
}

sauceTestWorker.drain(() => {
  process.exit(allTestsPassed ? 0 : 1);
});
<commit_msg>remote_runner: Delete commented-out browsers<commit_after>'use strict';

const async = require('async');
const wd = require('wd');

const config = {
  host: 'ondemand.saucelabs.com',
  port: 80,
  username: process.env.SAUCE_USER,
  accessKey: process.env.SAUCE_ACCESS_KEY,
};

const isAdminRunner = process.argv[2] === 'admin';

let allTestsPassed = true;
// overwrite the default exit code
// in case not all worker can be run (due to saucelabs limits),
// `queue.drain` below will not be called
// and the script would silently exit with error code 0
process.exitCode = 2;
process.on('exit', (code) => {
  if (code === 2) {
    console.log('\x1B[31mFAILED\x1B[39m Not all saucelabs runner have been started.');
  }
});

const sauceTestWorker = async.queue((testSettings, callback) => {
  const browser = wd.promiseChainRemote(
      config.host, config.port, config.username, config.accessKey);
  const name = [process.env.GIT_HASH].concat(process.env.SAUCE_NAME || []).concat([
    `${testSettings.browserName} ${testSettings.version}, ${testSettings.platform}`,
  ]).join(' - ');
  testSettings.name = name;
  testSettings.public = true;
  testSettings.build = process.env.GIT_HASH;
  // console.json can be downloaded via saucelabs,
  // don't know how to print them into output of the tests
  testSettings.extendedDebugging = true;
  testSettings.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;

  browser.init(testSettings).get('http://localhost:9001/tests/frontend/', () => {
    const url = `https://saucelabs.com/jobs/${browser.sessionID}`;
    console.log(`Remote sauce test '${name}' started! ${url}`);

    // tear down the test excecution
    const stopSauce = (success, timesup) => {
      clearInterval(getStatusInterval);
      clearTimeout(timeout);

      browser.quit(() => {
        if (!success) {
          allTestsPassed = false;
        }

        // if stopSauce is called via timeout
        // (in contrast to via getStatusInterval) than the log of up to the last
        // five seconds may not be available here. It's an error anyway, so don't care about it.
        printLog(logIndex);

        if (timesup) {
          console.log(`[${testSettings.browserName} ${testSettings.platform}` +
            `${testSettings.version === '' ? '' : (` ${testSettings.version}`)}]` +
            ' \x1B[31mFAILED\x1B[39m allowed test duration exceeded');
        }
        console.log(`Remote sauce test '${name}' finished! ${url}`);

        callback();
      });
    };

    /**
       * timeout if a test hangs or the job exceeds 14.5 minutes
       * It's necessary because if travis kills the saucelabs session due to inactivity,
       * we don't get any output
       * @todo this should be configured in testSettings, see
       * https://wiki.saucelabs.com/display/DOCS/Test+Configuration+Options#TestConfigurationOptions-Timeouts
       */
    const timeout = setTimeout(() => {
      stopSauce(false, true);
    }, 870000); // travis timeout is 15 minutes, set this to a slightly lower value

    let knownConsoleText = '';
    // how many characters of the log have been sent to travis
    let logIndex = 0;
    const getStatusInterval = setInterval(() => {
      browser.eval("$('#console').text()", (err, consoleText) => {
        if (!consoleText || err) {
          return;
        }
        knownConsoleText = consoleText;

        if (knownConsoleText.indexOf('FINISHED') > 0) {
          const match = knownConsoleText.match(
              /FINISHED.*([0-9]+) tests passed, ([0-9]+) tests failed/);
          // finished without failures
          if (match[2] && match[2] === '0') {
            stopSauce(true);

            // finished but some tests did not return or some tests failed
          } else {
            stopSauce(false);
          }
        } else {
          // not finished yet
          printLog(logIndex);
          logIndex = knownConsoleText.length;
        }
      });
    }, 5000);

    /**
       * Replaces color codes in the test runners log, appends
       * browser name, platform etc. to every line and prints them.
       *
       * @param {number} index offset from where to start
       */
    const printLog = (index) => {
      let testResult = knownConsoleText.substring(index)
          .replace(/\[red\]/g, '\x1B[31m').replace(/\[yellow\]/g, '\x1B[33m')
          .replace(/\[green\]/g, '\x1B[32m').replace(/\[clear\]/g, '\x1B[39m');
      testResult = testResult.split('\\n').map((line) => `[${testSettings.browserName} ` +
        `${testSettings.platform}` +
        `${testSettings.version === '' ? '' : (` ${testSettings.version}`)}]` +
        `${line}`).join('\n');

      console.log(testResult);
    };
  });
}, 6); // run 6 tests in parrallel

if (!isAdminRunner) {
  sauceTestWorker.push({
    platform: 'Windows 10',
    browserName: 'firefox',
    version: '84.0',
  });
  sauceTestWorker.push({
    platform: 'Windows 7',
    browserName: 'chrome',
    version: '55.0',
    args: ['--use-fake-device-for-media-stream'],
  });
  sauceTestWorker.push({
    platform: 'OS X 10.15',
    browserName: 'safari',
    version: '13.1',
  });
  sauceTestWorker.push({
    platform: 'Windows 10',
    browserName: 'microsoftedge',
    version: '83.0',
  });
  sauceTestWorker.push({
    platform: 'Windows 7',
    browserName: 'firefox',
    version: '78.0',
  });
} else {
  sauceTestWorker.push({
    platform: 'OS X 10.15',
    browserName: 'safari',
    version: '13.1',
  });
}

sauceTestWorker.drain(() => {
  process.exit(allTestsPassed ? 0 : 1);
});
<|endoftext|>


<commit_before>var JqueryCrudManager = CrudManager.extend({
    executeAddWithUI: function (url) {
        var self = this;
        var dict = this.extractFromModal(this.addModal, 'add');
        var params = this.extractToBackend(dict);

        $.ajax({
            url: url
            , type: 'POST'
            , data: params
            , success: function(res) {
                self.panelBody.append(self.genBodyRow(
                    self,
                    self.getNextRowId(),
                    self.convertToInternal(dict)
                ));

                self.editingCallback();
            }
            , error: self.onBackendError.bind(self, 'add')
        });
    },
    executeUpdateWithUI: function (url, $row) {
        var self = this;
        var dict = this.extractFromModal(this.editModal, 'edit');
        var params = this.extractToBackend(dict);

        $.ajax({
            url: url +'' + dict['id']
            , type: 'PUT'
            , data: params
            , success: function(res) {
                var data = self.convertToInternal(dict);
                var $updatedRow = self.genBodyRow(self, parseInt($row.attr('data-id')), data);
                replaceDom($updatedRow, $row);

                self.editingCallback();
            }
            , error: self.onBackendError.bind(self, 'update')
        });
    },
    executeRemoveWithUI: function (url, $row) {
        var self = this;
        var id = $row.find('.id').text().trim();

        $.ajax({
            url: url +'' + id
            , type: 'DELETE'
            , success: function(res) {
                self.editingCallback();

                $row.remove();
            }
            , error: self.onBackendError.bind(self, 'remove')
        });
    }
});<commit_msg>add callback on jquery crud manager<commit_after>var JqueryCrudManager = CrudManager.extend({
    executeAddWithUI: function (url, callback) {
        var self = this;
        var dict = this.extractFromModal(this.addModal, 'add');
        var params = this.extractToBackend(dict);

        $.ajax({
            url: url
            , type: 'POST'
            , data: params
            , success: function(res) {
                var $row = self.genBodyRow(
                    self,
                    self.getNextRowId(),
                    self.convertToInternal(dict)
                );
                self.panelBody.append($row);

                self.editingCallback();
                if (callback) callback(res, $row);
            }
            , error: self.onBackendError.bind(self, 'add')
        });
    },
    executeUpdateWithUI: function (url, $row, callback) {
        var self = this;
        var dict = this.extractFromModal(this.editModal, 'edit');
        var params = this.extractToBackend(dict);

        $.ajax({
            url: url +'' + dict['id']
            , type: 'PUT'
            , data: params
            , success: function(res) {
                var data = self.convertToInternal(dict);
                var $updatedRow = self.genBodyRow(self, parseInt($row.attr('data-id')), data);
                replaceDom($updatedRow, $row);

                self.editingCallback();
                if (callback) callback(res, $updatedRow);
            }
            , error: self.onBackendError.bind(self, 'update')
        });
    },
    executeRemoveWithUI: function (url, $row, callback) {
        var self = this;
        var id = $row.find('.id').text().trim();

        $.ajax({
            url: url +'' + id
            , type: 'DELETE'
            , success: function(res) {
                self.editingCallback();
                if (callback) callback(res, $row);

                $row.remove();
            }
            , error: self.onBackendError.bind(self, 'remove')
        });
    }
});<|endoftext|>


<commit_before>(function() {

var NOP = function() {};

config = {
	annotations: {},
	extensions: {},
	commands: {
		deleteTiddler: {

		}
	},
	macros: {
		search: {},
		view: {
			views: {}
		}
	},
	shadowTiddlers: {
		ToolbarCommands: "|~ViewToolbar|closeTiddler closeOthers +editTiddler" +
			" > fields syncing permalink references jump|\n" +
			"|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|"
	}
};

Tiddler = function(title) {
	this.title = title;
	this.fields = {};
	this.tags = [];
};
Tiddler.prototype.incChangeCount = NOP;

TiddlyWiki = function() {
	this._tiddlers = {};
};
TiddlyWiki.prototype.getTiddler = function(title) {
	return this._tiddlers[title];
};
TiddlyWiki.prototype.saveTiddler = function(title, newTitle, newBody, modifier,
		modified, tags, fields, clearChangeCount, created, creator) {
	var tiddler = new Tiddler(newTitle);
	tiddler.creator = creator;
	tiddler.created = created;
	tiddler.modifier = modifier;
	tiddler.modified = modifier;
	tiddler.tags = tags;
	tiddler.text = newBody;
	tiddler.fields = fields;
	this._tiddlers[tiddler.title] = tiddler;
	return tiddler;
}
TiddlyWiki.prototype.removeTiddler = function(title) {
	delete this._tiddlers[title];
};
TiddlyWiki.prototype.addNotification = NOP;

store = new TiddlyWiki();

refreshStyles = NOP;
autoSaveChanges = NOP;

TiddlyWiki.prototype.isDirty = function() {
	return this.dirty;
};

TiddlyWiki.prototype.tiddlerExists = function(title) {
	return this._tiddlers[title] ? true : false;
};

TiddlyWiki.prototype.isShadowTiddler = function(title) {
	return config.shadowTiddlers[title] === undefined ? false : true;
};

Array.prototype.contains = function(item)
{
	return this.indexOf(item) != -1;
};

String.prototype.format = function(substrings)
{
	var subRegExp = /(?:%(\d+))/mg;
	var currPos = 0;
	var r = [];
	do {
		var match = subRegExp.exec(this);
		if(match && match[1]) {
			if(match.index > currPos)
				r.push(this.substring(currPos,match.index));
			r.push(substrings[parseInt(match[1])]);
			currPos = subRegExp.lastIndex;
		}
	} while(match);
	if(currPos < this.length)
		r.push(this.substring(currPos,this.length));
	return r.join("");
};

})();
<commit_msg>testing - fixtures<commit_after>(function() {

var NOP = function() {};

config = {
	annotations: {},
	extensions: {},
	commands: {
		deleteTiddler: {

		}
	},
	macros: {
		search: {},
		view: {
			views: {}
		}
	},
	shadowTiddlers: {
		ToolbarCommands: "|~ViewToolbar|closeTiddler closeOthers +editTiddler" +
			" > fields syncing permalink references jump|\n" +
			"|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|"
	}
};

Story = function() {};

Story.prototype = {
	refreshTiddler: function() {

	}
};
story = new Story();

Tiddler = function(title) {
	this.title = title;
	this.fields = {};
	this.tags = [];
};
Tiddler.prototype.incChangeCount = NOP;

TiddlyWiki = function() {
	this._tiddlers = {};
};
TiddlyWiki.prototype.getTiddler = function(title) {
	return this._tiddlers[title];
};
TiddlyWiki.prototype.saveTiddler = function(title, newTitle, newBody, modifier,
		modified, tags, fields, clearChangeCount, created, creator) {
	var tiddler = new Tiddler(newTitle);
	tiddler.creator = creator;
	tiddler.created = created;
	tiddler.modifier = modifier;
	tiddler.modified = modifier;
	tiddler.tags = tags;
	tiddler.text = newBody;
	tiddler.fields = fields;
	this._tiddlers[tiddler.title] = tiddler;
	return tiddler;
}
TiddlyWiki.prototype.removeTiddler = function(title) {
	delete this._tiddlers[title];
};
TiddlyWiki.prototype.addNotification = NOP;

store = new TiddlyWiki();

refreshStyles = NOP;
autoSaveChanges = NOP;

TiddlyWiki.prototype.isDirty = function() {
	return this.dirty;
};

TiddlyWiki.prototype.setDirty = function(dirty) {
	this.dirty = dirty ? true : false;
};

TiddlyWiki.prototype.tiddlerExists = function(title) {
	return this._tiddlers[title] ? true : false;
};

TiddlyWiki.prototype.isShadowTiddler = function(title) {
	return config.shadowTiddlers[title] === undefined ? false : true;
};

Array.prototype.contains = function(item)
{
	return this.indexOf(item) != -1;
};

String.prototype.format = function(substrings)
{
	var subRegExp = /(?:%(\d+))/mg;
	var currPos = 0;
	var r = [];
	do {
		var match = subRegExp.exec(this);
		if(match && match[1]) {
			if(match.index > currPos)
				r.push(this.substring(currPos,match.index));
			r.push(substrings[parseInt(match[1])]);
			currPos = subRegExp.lastIndex;
		}
	} while(match);
	if(currPos < this.length)
		r.push(this.substring(currPos,this.length));
	return r.join("");
};

})();
<|endoftext|>


<commit_before>/**
 * Created by Alain Dechorgnat on 24/02/14.
 */
var osdMapApp = angular.module('osdMapApp', [])
    .filter('duration', funcDurationFilter)
    .config(function($locationProvider) {$locationProvider.html5Mode(true);});

osdMapApp.controller('OsdMapCtrl', function OsdMapCtrl($scope, $http, $location , $window) {
    $scope.osds = [];
    $scope.dispoModes = ["up/down", "in/out" , "free space (%)"];
    $scope.dispoMode = "up/down";
    $scope.osdControl = 0;
    $scope.warningMessage = "";
    var dispoModeFilter = ($location.search()).dispoMode;
    if ((typeof dispoModeFilter !=="undefined")&&(dispoModeFilter.indexOf("space") > -1)) $scope.dispoMode = "free space (%)";
    // get OSD info and refresh every 10s
    getOsds();
    setInterval(function () {getOsds()},10*1000);

    // Prepare OSD topology from crushmap

    $http({method: "get", url: cephRestApiURL + "osd/crush/dump.json"}).
        success(function (data, status) {
            $scope.status = status;
            $scope.types = data.output.types;
            $scope.devices = data.output.devices;
            $scope.buckets = computeBucketsTree(data.output.buckets);
        }).
        error(function (data, status) {
            $scope.status = status;
        });

    function computeBucketsTree(rawbuckets) {
        var bucketsTab = [];
        var osdTab = [];

        // make array of buckets with bucket id as index
        for (var i = 0; i < rawbuckets.length; i++) {
            bucketsTab[rawbuckets[i].id] = rawbuckets[i];
        }
        // device's name for OSD (id >=0)
        for (var i = 0; i < $scope.devices.length; i++) {
            osdTab[$scope.devices[i].id] = $scope.devices[i].name;
        }
        // init tab with  bucket with id -1 as root
        var buckets = bucketsTab[-1];

        //recursively make the tree of buckets for the D3 sunburst viz
        addChildren(buckets);
        //console.error(JSON.stringify(buckets));
        return buckets;

        function addChildren(bucket) {
            bucket.dispo = 1.0;
            bucket.children = [];
            for (var j = 0; j < bucket.items.length; j++) {
                var item = bucket.items[j];
                if (item.id < 0) {
                    //item is not an OSD
                    bucket.children.push(bucketsTab[item.id]);
                    addChildren(bucketsTab[item.id]);
                }
                else {
                    //item is an OSD
                    var osd = item;
                    osd.name = osdTab[item.id];
                    //compute dispo if data is available
                    if (typeof $scope.osds[item.id] !== 'undefined') {
                        osd.dispo = $scope.dispo($scope.osds[item.id]);
                    }
                    else
                        osd.dispo = -1.0; //"unknown"
                    bucket.children.push(osd);
                }
            }
        }
    }

    function getOsds() {
        $http({method: "get", url: inkscopeCtrlURL + "ceph/osd?depth=2"})
            .success(function (data, status) {
                $scope.date = new Date();
                $scope.status = status;
                $scope.osds = [];
                $scope.osdOut = 0;
                $scope.osdDown = 0;
                $scope.warningMessage = "";
                for (var i = 0; i < data.length; i++) {
                    data[i].id = data[i].node._id;
                    if (!data[i].stat.in) $scope.osdOut++;
                    if (!data[i].stat.up) $scope.osdDown++;
                    data[i].lastControl = ((+$scope.date) - data[0].stat.timestamp) / 1000;
                    try {
                        data[i].free = data[i].partition.stat.free;
                        data[i].total = data[i].partition.stat.total;
                        data[i].percent = data[i].free/data[i].total;
                    }
                    catch (e) {
                        data[i].free = "N/A";
                        data[i].total = "N/A";
                        data[i].percent = -1;
                    }
                    $scope.osds[data[i].id] = data[i];
                }
                if ($scope.osdDown >0) $scope.warningMessage += " OSD down : "+$scope.osdDown ;
                if ($scope.osdOut >0)  $scope.warningMessage = $scope.warningMessage ==''? " OSD out : "+$scope.osdOut : $scope.warningMessage +" / OSD out : "+$scope.osdOut ;
                $scope.osdControl = data[0].lastControl;
                //console.log(JSON.stringify($scope.osds));
                $scope.refreshStatusDisplay();
            })
            .error(function (data, status) {
                $scope.status = status;
                $scope.data = data || "Request failed";
            });
    }

    $scope.dispo= function(node) {
        if (typeof node === undefined) return -1;
        if ($scope.dispoMode == "up/down") return node.stat.up ? 1.0 : 0.0;
        if ($scope.dispoMode == "in/out") return node.stat.in ? 1.0 : 0.2;
        if ($scope.dispoMode == "free space (%)") return (node.percent== -1 ? "N/A": node.percent);
    }

    $scope.refreshStatusDisplay = function () {
        if ((typeof $scope.osds !== 'undefined') &&
            (typeof $scope.buckets !== 'undefined')) {
            for (var i = 0; i < $scope.osds.length; i++) {
                //immediate update of osd sectors
                var path = d3.select("#osd" + $scope.osds[i].id);
                path.style("fill", color4ascPercent($scope.dispo($scope.osds[i])));

            }
        }
    }
    $scope.home = function(){
        $window.location.href = "index.html";
    }

});

osdMapApp.directive('myTopology', function () {

    return {
        restrict: 'EA',
        terminal: true,
        link: function (scope, element, attrs) {

            function click(d) {
                // fade out all text elements
                text.transition().attr("opacity", 0);

                path.transition()
                    .duration(750)
                    .attrTween("d", arcTween(d))
                    .each("end", function (e, i) {
                        // check if the animated element's data e lies within the visible angle span given in d
                        if (e.x >= d.x && e.x < (d.x + d.dx)) {
                            // get a selection of the associated text element
                            var arcText = d3.select(this.parentNode).select("text");
                            // fade in the text element and recalculate positions
                            arcText.transition().duration(750)
                                .attr("opacity", 1)
                                .attr("transform", function () {
                                    return "rotate(" + computeTextRotation(e) + ")"
                                })
                                .attr("x", function (d) {
                                    return y(d.y);
                                });
                        }
                    });
            }

            // Interpolate the scales!
            function arcTween(d) {
                var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
                    yd = d3.interpolate(y.domain(), [d.y, 1]),
                    yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
                return function (d, i) {
                    return i
                        ? function (t) {
                        return arc(d);
                    }
                        : function (t) {
                        x.domain(xd(t));
                        y.domain(yd(t)).range(yr(t));
                        return arc(d);
                    };
                };
            }

            function computeTextRotation(d) {
                return (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
            }
            /*function computeTextRotation(d) {
             var ang = (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
             return (ang > 90) ? 180 + ang : ang;
             }*/

            function description(d) {
                var html = "";
                html += "
" + d.name;
                if (d.id >=0) {//OSD state
                    var osdstate = (scope.osds[d.id].stat.in == true) ? "in / " : "out / ";
                    osdstate += (scope.osds[d.id].stat.up == true) ? "up" : "down";
                    html +=  "
"+osdstate ;

                }
                html += "
"

                html += "id : " + d.id + "
"
                html += "weight : " + d.weight + "
"
                if (typeof d.hash !== "undefined") {
                    html += "hash : " + d.hash + "
"
                }
                if (typeof d.alg !== "undefined") {
                    html += "alg : " + d.alg + "
"
                }
                if (typeof d.type_name !== "undefined") {
                    html += "type : " + d.type_name + "
"
                }
                if (typeof d.pos !== "undefined") {
                    html += "pos : " + d.pos + "
"
                }
                if (d.id >=0){
                    // OSD specific fields
                    html += "free space : " + funcBytes(scope.osds[d.id].free) + "
";
                    html += "total space : " + funcBytes(scope.osds[d.id].total) + "
";
                    html += "free : " +(scope.osds[d.id].free*100/scope.osds[d.id].total).toFixed(1) + "%
";
                }
                return html;
            }

            var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0];
            scope.screenSize = {"x": w.innerWidth || e.clientWidth || g.clientWidth, "y": w.innerHeight || e.clientHeight || g.clientHeight};

            var width = scope.screenSize.x - 40,
                height = scope.screenSize.y - 200,
                radius = Math.min(width, height) / 2 - 10;

            var x = d3.scale.linear()
                .range([0, 2 * Math.PI]);

            var color = d3.scale.category20c();

            var svg = d3.select(element[0])
                .append("svg")
                .attr("id","svgGraph")
                .attr("width", width)
                .attr("height", height)
                .append("g")
                .attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ")");

            var divTooltip = d3.select("body").select("#tooltip");

            function makeGraph(topology) {
                // clear the elements inside the directive
                svg.selectAll('*').remove();

                var width = scope.screenSize.x - 40,
                    height = scope.screenSize.y - 200,
                    radius = Math.min(width, height) / 2 - 10;

                var y = d3.scale.linear()
                    .range([0, radius]);

                svg.attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ")");
                var partition = d3.layout.partition()
                    .value(function (d) {
                        return d.weight;
                    });

                var arc = d3.svg.arc()
                    .startAngle(function (d) {
                        return Math.max(0, Math.min(2 * Math.PI, x(d.x)));
                    })
                    .endAngle(function (d) {
                        return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
                    })
                    .innerRadius(function (d) {
                        return Math.max(0, y(d.y));
                    })
                    .outerRadius(function (d) {
                        return Math.max(0, y(d.y + d.dy));
                    });

                var g = svg.selectAll("g")
                    .data(partition.nodes(topology))
                    .enter().append("g")
                    .on("click", click)
                    .on("mouseover", function (d) {
                        divTooltip.transition()
                            .duration(1000)
                            .style("opacity", .9);
                        divTooltip.html(description(d))
                            .style("left", (d3.event.pageX) + "px")
                            .style("top", (d3.event.pageY - 28) + "px")/**/;
                    })
                    .on("mouseout", function (d) {
                        divTooltip.transition()
                            .duration(1000)
                            .style("opacity", 0);
                    });

                var path = g.append("path")
                    .attr("d", arc)
                    .attr('id', function (d) {
                        return "osd" + d.id;
                    })
                    .style("fill", function (d) {
                        if ((typeof scope.osds !== "undefined")&&(typeof scope.osds[d.id] !== "undefined")&&(d.id>=0))
                            return color4ascPercent(scope.dispo(scope.osds[d.id]));
                        return color4ascPercent(d["dispo"]);
                    })
                    .style("stroke", "#fff")
                    .style("stroke-width", "1");
                /*var text = g.append("text")
                                  .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + computeTextRotation(d) + ")"; })
                                  .attr('text-anchor', function (d) { return computeTextRotation(d) > 180 ? "end" : "start"; })
                                  .attr("dx", "6") // margin
                                  .attr("dy", ".35em") // vertical-align
                                  .style("fill", "#fff")
                                  .text(function(d) { return d.name; });
                                  */

                var text = g.append("text")
                    .attr("transform", function (d) {
                        return "rotate(" + computeTextRotation(d) + ")";
                    })
                    .attr("x", function (d) {
                        return y(d.y);
                    })
                    .attr("dx", "6") // margin
                    .attr("dy", ".35em") // vertical-align
                    .style("fill", "#fff")
                    .text(function (d) {
                        return d.name;
                    });

                d3.select(self.frameElement).style("height",

                    height + "px");
            }

            scope.$watch('buckets', function (topology, oldTopology) {

                // if 'topology' is undefined, exit
                if (typeof topology === 'undefined') {
                    return;
                }

                makeGraph(topology);

            }, true);

            scope.$watch('screenSize', function (screenSize, oldscreenSize) {

                // if 'topology' is undefined, exit
                if (typeof screenSize === 'undefined') {
                    return;
                }

                makeGraph(scope.buckets);

            }, true);

        }
    }
})

/*javascript external to angular applies to a scope*/

function resizeGraphDiv() {
    var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0];
    x = w.innerWidth || e.clientWidth || g.clientWidth;
    y = w.innerHeight || e.clientHeight || g.clientHeight;

    d3.select("body").select("#put_the_graph_there")
        .attr("width", x - 40 +"px")
        .attr("height",y - 200 +"px");

    d3.select("body").select("#svgGraph")
        .attr("width", x - 40)
        .attr("height",y - 200);

    var domElt = document.getElementById('put_the_graph_there');
    var scope = angular.element(domElt).scope();
    scope.$apply(function() {
        scope.screenSize.x = x;
        scope.screenSize.y = y;
    });

    console.log("resizeGraphViz called: x="+(x-40)+", y="+(y-200));
}

//calling tellAngular on resize event
window.onresize = resizeGraphDiv;
<commit_msg>enhance tooltip and fix zoom in/ zoom out<commit_after>/**
 * Created by Alain Dechorgnat on 24/02/14.
 */
var osdMapApp = angular.module('osdMapApp', [])
    .filter('duration', funcDurationFilter)
    .config(function($locationProvider) {$locationProvider.html5Mode(true);});

osdMapApp.controller('OsdMapCtrl', function OsdMapCtrl($scope, $http, $location , $window) {
    $scope.osds = [];
    $scope.dispoModes = ["up/down", "in/out" , "free space (%)"];
    $scope.dispoMode = "up/down";
    $scope.osdControl = 0;
    $scope.warningMessage = "";
    var dispoModeFilter = ($location.search()).dispoMode;
    if ((typeof dispoModeFilter !=="undefined")&&(dispoModeFilter.indexOf("space") > -1)) $scope.dispoMode = "free space (%)";
    // get OSD info and refresh every 10s
    getOsds();
    setInterval(function () {getOsds()},10*1000);

    // Prepare OSD topology from crushmap

    $http({method: "get", url: cephRestApiURL + "osd/crush/dump.json"}).
        success(function (data, status) {
            $scope.status = status;
            $scope.types = data.output.types;
            $scope.devices = data.output.devices;
            $scope.buckets = computeBucketsTree(data.output.buckets);
        }).
        error(function (data, status) {
            $scope.status = status;
        });

    function computeBucketsTree(rawbuckets) {
        var bucketsTab = [];
        var osdTab = [];

        // make array of buckets with bucket id as index
        for (var i = 0; i < rawbuckets.length; i++) {
            bucketsTab[rawbuckets[i].id] = rawbuckets[i];
        }
        // device's name for OSD (id >=0)
        for (var i = 0; i < $scope.devices.length; i++) {
            osdTab[$scope.devices[i].id] = $scope.devices[i].name;
        }
        // init tab with  bucket with id -1 as root
        var buckets = bucketsTab[-1];

        //recursively make the tree of buckets for the D3 sunburst viz
        addChildren(buckets);
        //console.error(JSON.stringify(buckets));
        return buckets;

        function addChildren(bucket) {
            bucket.dispo = 1.0;
            bucket.children = [];
            for (var j = 0; j < bucket.items.length; j++) {
                var item = bucket.items[j];
                if (item.id < 0) {
                    //item is not an OSD
                    bucket.children.push(bucketsTab[item.id]);
                    addChildren(bucketsTab[item.id]);
                }
                else {
                    //item is an OSD
                    var osd = item;
                    osd.name = osdTab[item.id];
                    //compute dispo if data is available
                    if (typeof $scope.osds[item.id] !== 'undefined') {
                        osd.dispo = $scope.dispo($scope.osds[item.id]);
                    }
                    else
                        osd.dispo = -1.0; //"unknown"
                    bucket.children.push(osd);
                }
            }
        }
    }

    function getOsds() {
        $http({method: "get", url: inkscopeCtrlURL + "ceph/osd?depth=2"})
            .success(function (data, status) {
                $scope.date = new Date();
                $scope.status = status;
                $scope.osds = [];
                $scope.osdOut = 0;
                $scope.osdDown = 0;
                $scope.warningMessage = "";
                for (var i = 0; i < data.length; i++) {
                    data[i].id = data[i].node._id;
                    if (!data[i].stat.in) $scope.osdOut++;
                    if (!data[i].stat.up) $scope.osdDown++;
                    data[i].lastControl = ((+$scope.date) - data[0].stat.timestamp) / 1000;
                    try {
                        data[i].free = data[i].partition.stat.free;
                        data[i].total = data[i].partition.stat.total;
                        data[i].percent = data[i].free/data[i].total;
                    }
                    catch (e) {
                        data[i].free = "N/A";
                        data[i].total = "N/A";
                        data[i].percent = -1;
                    }
                    $scope.osds[data[i].id] = data[i];
                }
                if ($scope.osdDown >0) $scope.warningMessage += " OSD down : "+$scope.osdDown ;
                if ($scope.osdOut >0)  $scope.warningMessage = $scope.warningMessage ==''? " OSD out : "+$scope.osdOut : $scope.warningMessage +" / OSD out : "+$scope.osdOut ;
                $scope.osdControl = data[0].lastControl;
                //console.log(JSON.stringify($scope.osds));
                $scope.refreshStatusDisplay();
            })
            .error(function (data, status) {
                $scope.status = status;
                $scope.data = data || "Request failed";
            });
    }

    $scope.dispo= function(node) {
        if (typeof node === undefined) return -1;
        if ($scope.dispoMode == "up/down") return node.stat.up ? 1.0 : 0.0;
        if ($scope.dispoMode == "in/out") return node.stat.in ? 1.0 : 0.2;
        if ($scope.dispoMode == "free space (%)") return (node.percent== -1 ? "N/A": node.percent);
    }

    $scope.refreshStatusDisplay = function () {
        if ((typeof $scope.osds !== 'undefined') &&
            (typeof $scope.buckets !== 'undefined')) {
            for (var i = 0; i < $scope.osds.length; i++) {
                //immediate update of osd sectors
                var path = d3.select("#osd" + $scope.osds[i].id);
                path.style("fill", color4ascPercent($scope.dispo($scope.osds[i])));

            }
        }
    }
    $scope.home = function(){
        $window.location.href = "index.html";
    }

});

osdMapApp.directive('myTopology', function () {

    return {
        restrict: 'EA',
        terminal: true,
        link: function (scope, element, attrs) {

            function description(d) {
                var html = "";
                html += "
" + d.name;
                if (d.id >=0) {//OSD state
                    var osdstate = (scope.osds[d.id].stat.in == true) ? "in / " : "out / ";
                    osdstate += (scope.osds[d.id].stat.up == true) ? "up" : "down";
                    html +=  "
"+osdstate ;

                }
                html += "
"

                html += "id : " + d.id + "
"
                html += "weight : " + d.weight + "
"
                if (typeof d.hash !== "undefined") {
                    html += "hash : " + d.hash + "
"
                }
                if (typeof d.alg !== "undefined") {
                    html += "alg : " + d.alg + "
"
                }
                if (typeof d.type_name !== "undefined") {
                    html += "type : " + d.type_name + "
"
                }
                if (typeof d.pos !== "undefined") {
                    html += "pos : " + d.pos + "
"
                }
                if (d.id >=0){
                    // OSD specific fields
                    html += "free space : " + funcBytes(scope.osds[d.id].free) + "
";
                    html += "total space : " + funcBytes(scope.osds[d.id].total) + "
";
                    html += "free : " +(scope.osds[d.id].free*100/scope.osds[d.id].total).toFixed(1) + "%
";
                }
                return html;
            }

            var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0];
            scope.screenSize = {"x": w.innerWidth || e.clientWidth || g.clientWidth, "y": w.innerHeight || e.clientHeight || g.clientHeight};

            var width = scope.screenSize.x - 40,
                height = scope.screenSize.y - 200,
                radius = Math.min(width, height) / 2 - 10;

            var x = d3.scale.linear()
                .range([0, 2 * Math.PI]);

            var color = d3.scale.category20c();

            var svg = d3.select(element[0])
                .append("svg")
                .attr("id","svgGraph")
                .attr("width", width)
                .attr("height", height)
                .append("g")
                .attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ")");

            var divTooltip = d3.select("body").select("#tooltip");

            function makeGraph(topology) {
                // clear the elements inside the directive
                svg.selectAll('*').remove();

                var width = scope.screenSize.x - 40,
                    height = scope.screenSize.y - 200,
                    radius = Math.min(width, height) / 2 - 10;

                var y = d3.scale.linear()
                    .range([0, radius]);

                svg.attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ")");
                var partition = d3.layout.partition()
                    .value(function (d) {
                        return d.weight;
                    });

                var arc = d3.svg.arc()
                    .startAngle(function (d) {
                        return Math.max(0, Math.min(2 * Math.PI, x(d.x)));
                    })
                    .endAngle(function (d) {
                        return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
                    })
                    .innerRadius(function (d) {
                        return Math.max(0, y(d.y));
                    })
                    .outerRadius(function (d) {
                        return Math.max(0, y(d.y + d.dy));
                    });

                var g = svg.selectAll("g")
                    .data(partition.nodes(topology))
                    .enter().append("g")
                    .on("click",click )
                    .on("mousemove",function(){
                        divTooltip
                            .style("left", (d3.event.pageX + 10) + "px")
                            .style("top", (d3.event.pageY-150) + "px")/**/;
                    })
                    .on("mouseover", function (d) {
                        divTooltip.transition()
                            .duration(500)
                            .style("opacity", .9);
                        divTooltip.html(description(d));
                    })
                    .on("mouseout", function (d) {
                        divTooltip.transition()
                            .duration(500)
                            .style("opacity", 0);
                    });

                var path = g.append("path")
                    .attr("d", arc)
                    .attr('id', function (d) {
                        return "osd" + d.id;
                    })
                    .style("fill", function (d) {
                        if ((typeof scope.osds !== "undefined")&&(typeof scope.osds[d.id] !== "undefined")&&(d.id>=0))
                            return color4ascPercent(scope.dispo(scope.osds[d.id]));
                        return color4ascPercent(d["dispo"]);
                    })
                    .style("stroke", "#fff")
                    .style("stroke-width", "1");
                /*var text = g.append("text")
                                  .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + computeTextRotation(d) + ")"; })
                                  .attr('text-anchor', function (d) { return computeTextRotation(d) > 180 ? "end" : "start"; })
                                  .attr("dx", "6") // margin
                                  .attr("dy", ".35em") // vertical-align
                                  .style("fill", "#fff")
                                  .text(function(d) { return d.name; });
                                  */

                var text = g.append("text")
                    .attr("transform", function (d) {
                        return "rotate(" + computeTextRotation(d) + ")";
                    })
                    .attr("x", function (d) {
                        return y(d.y);
                    })
                    .attr("dx", "6") // margin
                    .attr("dy", ".35em") // vertical-align
                    .style("fill", "#fff")
                    .text(function (d) {
                        return d.name;
                    });

                function click(d) {
                    // fade out all text elements
                    text.transition().attr("opacity", 0);

                    path.transition()
                        .duration(750)
                        .attrTween("d", arcTween(d))
                        .each("end", function (e, i) {
                            // check if the animated element's data e lies within the visible angle span given in d
                            if (e.x >= d.x && e.x < (d.x + d.dx)) {
                                // get a selection of the associated text element
                                var arcText = d3.select(this.parentNode).select("text");
                                // fade in the text element and recalculate positions
                                arcText.transition().duration(750)
                                    .attr("opacity", 1)
                                    .attr("transform", function () {
                                        return "rotate(" + computeTextRotation(e) + ")"
                                    })
                                    .attr("x", function (d) {
                                        return y(d.y);
                                    });
                            }
                        });
                }

                d3.select(self.frameElement).style("height", height + "px");

                // Interpolate the scales!
                function arcTween(d) {
                    var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
                        yd = d3.interpolate(y.domain(), [d.y, 1]),
                        yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
                    return function (d, i) {
                        return i
                            ? function (t) {
                            return arc(d);
                        }
                            : function (t) {
                            x.domain(xd(t));
                            y.domain(yd(t)).range(yr(t));
                            return arc(d);
                        };
                    };
                }

                function computeTextRotation(d) {
                    return (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
                }
                /*function computeTextRotation(d) {
                 var ang = (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
                 return (ang > 90) ? 180 + ang : ang;
                 }*/

            }

            scope.$watch('buckets', function (topology, oldTopology) {

                // if 'topology' is undefined, exit
                if (typeof topology === 'undefined') {
                    return;
                }

                makeGraph(topology);

            }, true);

            scope.$watch('screenSize', function (screenSize, oldscreenSize) {

                // if 'topology' is undefined, exit
                if (typeof screenSize === 'undefined') {
                    return;
                }

                makeGraph(scope.buckets);

            }, true);

        }
    }
})

/*javascript external to angular applies to a scope*/

function resizeGraphDiv() {
    var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0];
    x = w.innerWidth || e.clientWidth || g.clientWidth;
    y = w.innerHeight || e.clientHeight || g.clientHeight;

    d3.select("body").select("#put_the_graph_there")
        .attr("width", x - 40 +"px")
        .attr("height",y - 200 +"px");

    d3.select("body").select("#svgGraph")
        .attr("width", x - 40)
        .attr("height",y - 200);

    var domElt = document.getElementById('put_the_graph_there');
    var scope = angular.element(domElt).scope();
    scope.$apply(function() {
        scope.screenSize.x = x;
        scope.screenSize.y = y;
    });

    console.log("resizeGraphViz called: x="+(x-40)+", y="+(y-200));
}

//calling tellAngular on resize event
window.onresize = resizeGraphDiv;
<|endoftext|>


<commit_before>/*
*
* USAGE:
* $(window).baseScoll();
*
*/

(function($){

	$.fn.baseScroll = function(options) {

		var defaults = {
			link: 'a',
			sectionLinks: '.nav a',
			speed: 1500,
			offset: 100,
		};
		var options = $.extend(defaults, options);

		return this.each(function() {

			// smooth scrolling for specified anchor links
			$(options.link).click( function() {
				var anchor = $(this).attr('href').replace('/','');
				if (anchor.indexOf('#') < 0) return true; // halt if not anchor

				var position = $(anchor).offset();
				var top = position.top;

				$('html, body').animate({
					scrollTop: top - options.offset,
				}, options.speed);

				return false;
			});

			var index = [];

			// get the offset of each linked element
			$sectionLinks = $(options.sectionLinks);
			$sectionLinks.each( function() {

				var anchor = $(this).attr('href');

				if (anchor.indexOf('#') >= 0) {

					anchor = anchor.replace('/','');

					var position = $(anchor).offset();

					if (!position == undefined)
						var top = position.top - options.offset;

					anchor = anchor.replace('#','');
					index[anchor] = top;

				}

			});

			var offsets = [];
			for (var anchor in index) offsets.push([anchor, index[anchor]]);

			offsets.sort(function(a, b) {
			    a = a[1];
			    b = b[1];
			    return a < b ? -1 : (a > b ? 1 : 0);
			});

			function navChange(anchor) {
				$(options.sectionLinks).parent().removeClass("active");
				$(options.sectionLinks+'[href*=#'+anchor+']').parent().addClass("active");
			}

			$(window).scroll( function() {
				var scroll = $(this).scrollTop();

				for (var i = 0; i < offsets.length; i++) {
					var n = (i < (offsets.length-1) ? (i+1) : false);

					if (n && scroll > offsets[i][1] && scroll < offsets[n][1]) {
						navChange(offsets[i][0]);
					}
					if (!n && scroll > offsets[i][1]) {
				   		navChange(offsets[i][0]);
					}
				}

				if (scroll < offsets[0][1]) {
					$(options.sectionLinks).parent().removeClass("active");
				}
			});

		});
	};

})(jQuery);<commit_msg>Fix element check conditional<commit_after>/*
*
* USAGE:
* $(window).baseScoll();
*
*/

(function($){

	$.fn.baseScroll = function(options) {

		var defaults = {
			link: 'a',
			sectionLinks: '.nav a',
			speed: 1500,
			offset: 100,
		};
		var options = $.extend(defaults, options);

		return this.each(function() {

			// smooth scrolling for specified anchor links
			$(options.link).click( function() {
				var anchor = $(this).attr('href').replace('/','');
				if (anchor.indexOf('#') < 0) return true; // halt if not anchor

				var position = $(anchor).offset();
				var top = position.top;

				$('html, body').animate({
					scrollTop: top - options.offset + 30,
				}, options.speed);

				return false;
			});

			var index = [];

			// get the offset of each linked element
			$sectionLinks = $(options.sectionLinks);
			$sectionLinks.each( function() {

				var anchor = $(this).attr('href');

				if (anchor.indexOf('#') >= 0) {

					anchor = anchor.replace('/','');

					if ( $(anchor).length > 0 ) {

						var position = $(anchor).offset();
						var top = position.top - options.offset;

						anchor = anchor.replace('#','');
						index[anchor] = top;

					}

				}

			});

			var offsets = [];
			for (var anchor in index) offsets.push([anchor, index[anchor]]);

			offsets.sort(function(a, b) {
			    a = a[1];
			    b = b[1];
			    return a < b ? -1 : (a > b ? 1 : 0);
			});

			function navChange(anchor) {
				$(options.sectionLinks).parent().removeClass("active");
				$(options.sectionLinks+'[href*=#'+anchor+']').parent().addClass("active");
			}

			$(window).scroll( function() {
				var scroll = $(this).scrollTop();

				for (var i = 0; i < offsets.length; i++) {
					var n = (i < (offsets.length-1) ? (i+1) : false);

					if (n && scroll > offsets[i][1] && scroll < offsets[n][1]) {
						navChange(offsets[i][0]);
					}
					if (!n && scroll > offsets[i][1]) {
				   		navChange(offsets[i][0]);
					}
				}

				if (scroll < offsets[0][1]) {
					$(options.sectionLinks).parent().removeClass("active");
				}
			});

		});
	};

})(jQuery);<|endoftext|>