<commit_before>
$(document).ready(function() {

	FB.init({
        appId      : '348725015219063', // App ID
        channelUrl : '//http://dev.asdfap.caffodiangmailcom.stackmobapp.com/channel.html', // Channel File
        status     : true, // check login status
        cookie     : true, // enable cookies to allow the server to access the session
        xfbml      : true  // parse XFBML
      });
        // listen for and handle auth.statusChange events
        FB.Event.subscribe('auth.statusChange', function(response) {
          if (response.authResponse) {
            // user has auth'd your app and is logged into Facebook
            FB.api('/me', function(me){
              if (me.name) {
                document.getElementById('auth-displayname').innerHTML = me.name;
              }
            })
            document.getElementById('auth-loggedout').style.display = 'none';
            document.getElementById('auth-loggedin').style.display = 'block';

            getLikes();
          } else {
            // user has not auth'd your app, or is not logged into Facebook
            document.getElementById('auth-loggedout').style.display = 'block';
            document.getElementById('auth-loggedin').style.display = 'none';
          }
        });

        // respond to clicks on the login and logout links
        document.getElementById('auth-loginlink').addEventListener('click', function(){
            FB.login(function(response) {
              if (response.authResponse) {
                var accessToken = response.authResponse.accessToken;
                FB.api('/me', function(response) {
                  var user = new StackMob.User({ username: response.email });
                  user.createUserWithFacebook(accessToken);
                });
              } else {
                console.log('User cancelled login or did not fully authorize.');
              }
            }, {scope: 'email, user_likes'});
          }
        );
        document.getElementById('auth-logoutlink').addEventListener('click', function(){
          FB.logout();
        });

});

var getLikes = function() {
	FB.api('/me/likes', function(response) {
		for (var x in response.data) {
			var item = response.data[x];

			if (isOwnable(item))  {
				var newDiv = $('<div/>', {
   					 html: item.name,
   					});
				$('#items').append(newDiv);
			}
		}

	});
}

var isOwnable = function(fbObject) {
	if (fbObject.category == "Games/toys" || fbObject.category == "Book") {
		return true;
	}
	else return false;
}<commit_msg>click items to own them<commit_after>
$(document).ready(function() {

	FB.init({
        appId      : '348725015219063', // App ID
        channelUrl : '//http://dev.asdfap.caffodiangmailcom.stackmobapp.com/channel.html', // Channel File
        status     : true, // check login status
        cookie     : true, // enable cookies to allow the server to access the session
        xfbml      : true  // parse XFBML
      });
        // listen for and handle auth.statusChange events
        FB.Event.subscribe('auth.statusChange', function(response) {
          if (response.authResponse) {
            // user has auth'd your app and is logged into Facebook
            FB.api('/me', function(me){
              if (me.name) {
                document.getElementById('auth-displayname').innerHTML = me.name;
              }
            })
            document.getElementById('auth-loggedout').style.display = 'none';
            document.getElementById('auth-loggedin').style.display = 'block';

            getLikes();
          } else {
            // user has not auth'd your app, or is not logged into Facebook
            document.getElementById('auth-loggedout').style.display = 'block';
            document.getElementById('auth-loggedin').style.display = 'none';
          }
        });

        // respond to clicks on the login and logout links
        document.getElementById('auth-loginlink').addEventListener('click', function(){
          FB.login(function(response) {
            if (response.authResponse) {
              var accessToken = response.authResponse.accessToken;
              FB.api('/me', function(response) {
                var user = new StackMob.User({ username: response.email });
                user.createUserWithFacebook(accessToken);
              });
            } else {
              console.log('User cancelled login or did not fully authorize.');
            }
          }, {scope: 'email, user_likes'});
        }
        );
        document.getElementById('auth-logoutlink').addEventListener('click', function(){
          FB.logout();
        });
      });

var getLikes = function() {
	FB.api('/me/likes', function(response) {
		for (var x in response.data) {
			var item = response.data[x];

			if (isOwnable(item))  {
				var newDiv = $('<div/>', {
         html: item.name,
       });
        newDiv.click(function() {
          //add to the user's "ownage"
          FB.api('/me/asdfap-test:own', 'post', { object:item.id }, function(response) {
            alert("You owned "+item.id);
          });

        });
        $('#items').append(newDiv);
      }

    }
  });
}

var postOwn = function(itemid) {
  FB.api('/me/asdfap-test:own', 'post', { object:itemid }, function(response) {
    alert("You owned "+itemid);

  });
}

var isOwnable = function(fbObject) {
 if (fbObject.category == "Games/toys" || fbObject.category == "Book") {
  return true;
}
else return false;
}
<|endoftext|>


<commit_before>jest.mock("../src/httpGet")

// Register init to DOMContentLoaded event
require("../src/index")

const resetEnv = () => {
  // Set up our document body
  document.body.innerHTML =
    "

" +
    "
Loading...
" +
    "

" +
    "" +
    "  Source: " +
    ""

  // Reset document.location.hash
  document.location.hash = ""
}

describe("init", () => {
  beforeEach(resetEnv)

  test("displays an error if the gist request fails", () => {
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation(() => Promise.reject("Test error"))

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("error").innerHTML).toEqual("Error: Test error")
      expect(document.getElementById("error").style.display).toEqual("block")
      expect(document.getElementById("loading").style.display).toEqual("none")
    })
  })

  test("displays the index scene content", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" }
      }
    })
    const indexContent = "Once upon a time..."
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("error").style.display).toEqual("none")
      expect(document.getElementById("loading").style.display).toEqual("none")
      expect(document.getElementById("content").innerHTML).toContain("
Once upon a time...
")
    })
  })

  test("applies the default stylesheet when style.css is present", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" },
        "style.css": { raw_url: "http://gists/style.css" }
      }
    })
    const indexContent = "Once upon a time..."
    const styleContent = "body { background-color: black; }"
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
        case "http://gists/style.css":
          return Promise.resolve(styleContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementsByTagName("style")[0].innerHTML).toContain(styleContent)
    })
  })

  test("renders mustache tags", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" }
      }
    })
    const indexContent =
      "---\n" +
      "state:\n" +
      "  hero: Bob\n" +
      "---\n\n" +
      "Once upon a time {{hero}}..."
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("content").innerHTML).toContain("
Once upon a time Bob...
")
    })
  })
})

describe("scene transition", () => {
  beforeEach(resetEnv)

  test("displays the scene content", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" },
        "end.markdown": { raw_url: "http://gists/end.markdown" }
      }
    })
    const indexContent = "Once upon a time... [continue...](end)"
    const endContent = "The end"
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
        case "http://gists/end.markdown":
          return Promise.resolve(endContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("content").innerHTML).toContain("Once upon a time...")

      // Dispatch scene transition
      document.querySelector("a[href=end]").click()
    }).then(() => {
      return new Promise(process.nextTick)
    }).then(() => {
      expect(document.getElementById("content").innerHTML).toContain("The end")
    })
  })
})
<commit_msg>Reset document.head<commit_after>jest.mock("../src/httpGet")

// Register init to DOMContentLoaded event
require("../src/index")

const resetEnv = () => {
  // Set up our document head
  document.head.innerHTML = ""
  // Set up our document body
  document.body.innerHTML =
    "

" +
    "
Loading...
" +
    "

" +
    "" +
    "  Source: " +
    ""

  // Reset document.location.hash
  document.location.hash = ""
}

describe("init", () => {
  beforeEach(resetEnv)

  test("displays an error if the gist request fails", () => {
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation(() => Promise.reject("Test error"))

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("error").innerHTML).toEqual("Error: Test error")
      expect(document.getElementById("error").style.display).toEqual("block")
      expect(document.getElementById("loading").style.display).toEqual("none")
    })
  })

  test("displays the index scene content", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" }
      }
    })
    const indexContent = "Once upon a time..."
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("error").style.display).toEqual("none")
      expect(document.getElementById("loading").style.display).toEqual("none")
      expect(document.getElementById("content").innerHTML).toContain("
Once upon a time...
")
    })
  })

  test("applies the default stylesheet when style.css is present", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" },
        "style.css": { raw_url: "http://gists/style.css" }
      }
    })
    const indexContent = "Once upon a time..."
    const styleContent = "body { background-color: black; }"
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
        case "http://gists/style.css":
          return Promise.resolve(styleContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementsByTagName("style")[0].innerHTML).toContain(styleContent)
    })
  })

  test("renders mustache tags", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" }
      }
    })
    const indexContent =
      "---\n" +
      "state:\n" +
      "  hero: Bob\n" +
      "---\n\n" +
      "Once upon a time {{hero}}..."
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("content").innerHTML).toContain("
Once upon a time Bob...
")
    })
  })
})

describe("scene transition", () => {
  beforeEach(resetEnv)

  test("displays the scene content", () => {
    const gistContent = JSON.stringify({
      files: {
        "index.markdown": { raw_url: "http://gists/index.markdown" },
        "end.markdown": { raw_url: "http://gists/end.markdown" }
      }
    })
    const indexContent = "Once upon a time... [continue...](end)"
    const endContent = "The end"
    const httpGet = require("../src/httpGet")
    httpGet.default.mockImplementation((url) => {
      switch (url) {
        case "http://gists/index.markdown":
          return Promise.resolve(indexContent)
        case "http://gists/end.markdown":
          return Promise.resolve(endContent)
      }
      return Promise.resolve(gistContent)
    })

    // Dispatch the DOMContentLoaded event
    document.dispatchEvent(new Event("DOMContentLoaded"))

    return new Promise(process.nextTick).then(() => {
      expect(document.getElementById("content").innerHTML).toContain("Once upon a time...")

      // Dispatch scene transition
      document.querySelector("a[href=end]").click()
    }).then(() => {
      return new Promise(process.nextTick)
    }).then(() => {
      expect(document.getElementById("content").innerHTML).toContain("The end")
    })
  })
})
<|endoftext|>


<commit_before>'use strict'

const id = 'subsystem'

const validSubsystems = [
  'benchmark'
, 'build'
, 'bootstrap'
, 'deps'
, 'doc'
, 'errors'
, 'etw'
, 'esm'
, 'inspector'
, 'lib'
, 'loader'
, 'meta'
, 'msi'
, 'node'
, 'n-api'
, 'perfctr'
, 'src'
, 'test'
, 'tools'
, 'win'

  // core libs
, 'assert'
, 'async_hooks'
, 'buffer'
, 'child_process'
, 'cluster'
, 'console'
, 'constants'
, 'crypto'
, 'debugger'
, 'dgram'
, 'dns'
, 'domain'
, 'events'
, 'fs'
, 'http'
, 'http2'
, 'https'
, 'inspector'
, 'module'
, 'net'
, 'os'
, 'path'
, 'perf_hooks'
, 'process'
, 'punycode'
, 'querystring'
, 'readline'
, 'repl'
, 'stream'
, 'string_decoder'
, 'sys'
, 'timers'
, 'tls'
, 'trace_events'
, 'tty'
, 'url'
, 'util'
, 'v8'
, 'vm'
, 'zlib'
]

module.exports = {
  id: id
, meta: {
    description: 'enforce subsystem validity'
  , recommended: true
  }
, defaults: {
    subsystems: validSubsystems
  }
, options: {
    subsystems: validSubsystems
  }
, validate: (context, rule) => {
    const subs = rule.options.subsystems
    const parsed = context.toJSON()
    if (!parsed.subsystems.length) {
      if (!parsed.release && !parsed.working) {
        // Missing subsystem
        context.report({
          id: id
        , message: 'Missing subsystem.'
        , string: parsed.title
        , line: 0
        , column: 0
        , level: 'fail'
        , wanted: subs
        })
      } else {
        context.report({
          id: id
        , message: 'Release commits do not have subsystems'
        , string: ''
        , level: 'skip'
        })
      }
    } else {
      var failed = false
      for (const sub of parsed.subsystems) {
        if (!~subs.indexOf(sub)) {
          failed = true
          // invalid subsystem
          const column = parsed.title.indexOf(sub)
          context.report({
            id: id
          , message: `Invalid subsystem: "${sub}"`
          , string: parsed.title
          , line: 0
          , column: column
          , level: 'fail'
          , wanted: subs
          })
        }
      }

      if (!failed) {
        context.report({
          id: id
        , message: 'valid subsystems'
        , string: parsed.subsystems.join(',')
        , level: 'pass'
        })
      }
    }
  }
}
<commit_msg>add worker as a subsystem<commit_after>'use strict'

const id = 'subsystem'

const validSubsystems = [
  'benchmark'
, 'build'
, 'bootstrap'
, 'deps'
, 'doc'
, 'errors'
, 'etw'
, 'esm'
, 'inspector'
, 'lib'
, 'loader'
, 'meta'
, 'msi'
, 'node'
, 'n-api'
, 'perfctr'
, 'src'
, 'test'
, 'tools'
, 'win'

  // core libs
, 'assert'
, 'async_hooks'
, 'buffer'
, 'child_process'
, 'cluster'
, 'console'
, 'constants'
, 'crypto'
, 'debugger'
, 'dgram'
, 'dns'
, 'domain'
, 'events'
, 'fs'
, 'http'
, 'http2'
, 'https'
, 'inspector'
, 'module'
, 'net'
, 'os'
, 'path'
, 'perf_hooks'
, 'process'
, 'punycode'
, 'querystring'
, 'readline'
, 'repl'
, 'stream'
, 'string_decoder'
, 'sys'
, 'timers'
, 'tls'
, 'trace_events'
, 'tty'
, 'url'
, 'util'
, 'v8'
, 'vm'
, 'worker'
, 'zlib'
]

module.exports = {
  id: id
, meta: {
    description: 'enforce subsystem validity'
  , recommended: true
  }
, defaults: {
    subsystems: validSubsystems
  }
, options: {
    subsystems: validSubsystems
  }
, validate: (context, rule) => {
    const subs = rule.options.subsystems
    const parsed = context.toJSON()
    if (!parsed.subsystems.length) {
      if (!parsed.release && !parsed.working) {
        // Missing subsystem
        context.report({
          id: id
        , message: 'Missing subsystem.'
        , string: parsed.title
        , line: 0
        , column: 0
        , level: 'fail'
        , wanted: subs
        })
      } else {
        context.report({
          id: id
        , message: 'Release commits do not have subsystems'
        , string: ''
        , level: 'skip'
        })
      }
    } else {
      var failed = false
      for (const sub of parsed.subsystems) {
        if (!~subs.indexOf(sub)) {
          failed = true
          // invalid subsystem
          const column = parsed.title.indexOf(sub)
          context.report({
            id: id
          , message: `Invalid subsystem: "${sub}"`
          , string: parsed.title
          , line: 0
          , column: column
          , level: 'fail'
          , wanted: subs
          })
        }
      }

      if (!failed) {
        context.report({
          id: id
        , message: 'valid subsystems'
        , string: parsed.subsystems.join(',')
        , level: 'pass'
        })
      }
    }
  }
}
<|endoftext|>


<commit_before>/*global html,isHostObjectProperty */

var findProprietaryStyle;
if(html && isHostObjectProperty(html, "style")){
  findProprietaryStyle = function (style, el){
    if ('string' != typeof el.style[style]){
        style = style.charAt(0).toUpperCase() + style.substring(1);
        var prefixes = ['Moz', 'O', 'Khtml', 'Webkit', 'ms'];
        for (var i = prefixes.length; i--; ) {
        if ('undefined' != typeof el.style[prefixes[i] + style]){
          return prefixes[i] + style;
        }
      }
      return null;
	}
    return style;
  };
}

<commit_msg>Tried to improve file for merging<commit_after>/*global html,isHostObjectProperty */

var findProprietaryStyle;

if(html && isHostObjectProperty(html, "style")){
	findProprietaryStyle = function (style, el) {
		if ('string' != typeof el.style[style]) {
			style = style.charAt(0).toUpperCase() + style.substring(1);
			var prefixes = ['Moz', 'O', 'Khtml', 'Webkit', 'Ms'];
			for (var i = prefixes.length; i--; ) {
				if ('undefined' != typeof el.style[prefixes[i] + style]) {
					return prefixes[i] + style;
				}
			}
			return null;
		}
		return style;
	};
}<|endoftext|>


<commit_before>'use strict';

var _ = require('sdk/l10n').get;
var Widget = require('sdk/widget').Widget;
var Hotkey = require('sdk/hotkeys').Hotkey;
var getFocusedElement = require('window/utils').getFocusedElement;

var debug = require('./debug').debug;

var KeyMonitor = require('./key-monitor').KeyMonitor;
var IMEOutput = require('./ime-output').IMEOutput;
var IMEWorkerManager = require('./ime-worker-manager').IMEWorkerManager;
var IMEDisplayManager = require('./ime-display-manager').IMEDisplayManager;

var IMEFrontend = {
  active: false,
  inputActive: false,

  candidateSelectionMode: false,

  pendingsymbols: '',
  candidates: [],
  candidatePage: 0,

  // XXX: make this configable
  hotkeyCombo: 'accel-alt-1',

  init: function if_init() {
    debug('[if/init]');
    // Show an widget
    this.widget = Widget({
      id: 'jszhuyin-indicator',
      label: _('JSZhuyin IME'),
      content: _('A')
    });

    // Register a hot key for toggling
    Hotkey({
      combo: this.hotkeyCombo,
      onPress: this.toggle.bind(this)
    });

    this.keyMonitor = new KeyMonitor(this);
    this.workerManager = new IMEWorkerManager(this);
    this.displayManager = new IMEDisplayManager(this);
    this.output = new IMEOutput();
  },

  toggle: function if_toggle() {
    debug('[if/toggle]');
    if (!this.active) {
      this.start();
    } else {
      this.stop();
    }
  },

  start: function if_start() {
    if (this.active)
      return;

    debug('[if/start]');
    this.active = true;

    this.widget.content = 'ㄅ';

    this.displayManager.start();
    this.keyMonitor.start();
    this.workerManager.start();
  },

  stop: function if_stop() {
    if (!this.active)
      return;

    debug('[if/stop]');
    this.active = false;

    this.widget.content = 'A';
    this.stopInput();

    this.displayManager.start();
    this.keyMonitor.stop();
    this.workerManager.stop();
  },

  updateInput: function if_updateInput() {
    debug('[if/updateInput]');
    var focusedElement = getFocusedElement();
    if (this.output.canHandle(focusedElement)) {
      this.startInput(focusedElement);
    } else {
      this.stopInput();
    }
  },

  startInput: function if_startInput(focusedElement) {
    debug('[if/startInput]');
    this.inputActive = true;

    this.output.setFocusedElement(focusedElement);
  },

  stopInput: function if_stopInput() {
    debug('[if/stopInput]');
    if (!this.inputActive)
      return;

    this.inputActive = false;

    this.candidateSelectionMode = false;

    this.pendingsymbols = '';
    this.candidates = [];
    this.candidatePage = 0;
    this.toggleIMEDisplay();

    this.output.finishComposition('');
    this.output.setFocusedElement(null);
    this.workerManager.sendMessage('handleKeyEvent', 0x1b /* ESCAPE */);
  },

  setCandidateSelectionMode: function if_setCandidateSelectionMode(mode) {
    this.displayManager.sendMessage('candidateselectionmode', mode);
    this.candidateSelectionMode = mode;
  },

  toggleIMEDisplay: function if_toggleIMEDisplay() {
    if (this.pendingsymbols || this.candidates.length) {
      this.displayManager.show(getFocusedElement());
      this.keyMonitor.blockKeyUpDownEvent = true;
    } else if (this.displayManager.isShowing()) {
      this.displayManager.hide();
      this.keyMonitor.blockKeyUpDownEvent = false;
    }
  },

  handleWorkerMessage: function if_handleWorkerResult(name, data) {
    switch (name) {
      case 'compositionupdate':
        if (!this.inputActive)
          return;

        this.pendingsymbols = data;
        this.output.setComposition(data);
        this.toggleIMEDisplay();
        break;

      case 'candidateschange':
        if (!this.inputActive)
          return;

        this.candidates = data;
        this.candidatePage = 0;
        this.displayManager.sendMessage('candidates', data);
        this.toggleIMEDisplay();
        if (!this.candidates.length && this.candidateSelectionMode) {
          this.setCandidateSelectionMode(false);
        }
        break;

      case 'compositionend':
        this.output.finishComposition(data);
        break;
    }
  },

  handleDisplayMessage: function if_handleDisplayMessage(name, data) {
    switch (name) {
      case 'select':
        this.workerManager.sendMessage('selectCandidate', data);
        break;
    }
  },

  handleKeyEvent: function if_handleKeyEvent(keyCode, charCode, symbolCode) {
    this.updateInput();
    if (!this.inputActive)
      return false;

    // escape key: stop input mode immediately
    if (keyCode === 27) {
      this.stopInput();
      return true;
    }

    if (this.candidateSelectionMode) {
      // A non-printable character will come with charCode = 0,
      // let's squeeze these two code into one variable to simplify the logic.
      var charKeyCode = charCode || keyCode;

      var page = this.candidatePage;

      switch (charKeyCode) {
        case 8: // Backspace key: leave selection mode
          this.setCandidateSelectionMode(false);

          // IME engine will need to handle this bug too
          if (this.pendingsymbols) {
            // Let engine handles backspace
            this.workerManager.sendMessage('handleKeyEvent', keyCode);
          } else {
            // Let default handing to run instead.
            // return false;
            // ... or, remove the selection panel altogether w/o deleting
            // text that is sent?
            this.stopInput();
          }
          break;

        case 13: // Enter key: select 1st selection of the page
          if (!this.candidates[page * 9])
            break;

          this.workerManager.sendMessage('selectCandidate', this.candidates[page * 9]);
          break;

        case 37: // Left arrow key: flip candidate selection page
          if (page === 0)
            break;

          page = this.candidatePage -= 1;
          this.displayManager.sendMessage('candidateselectionpage', page);
          break;

        case 38: // Up arrow key: leaving candidate selection mode
          if (page !== 0) {
            page = 0;
            this.displayManager.sendMessage('candidateselectionpage', page);
          }

          this.setCandidateSelectionMode(false);
          break;

        case 39: // Right arrow key: flip candidate selection page
          if ((page + 1) * 9 >= this.candidates.length)
            break;

          page = this.candidatePage += 1;
          this.displayManager.sendMessage('candidateselectionpage', page);
          break;

        default:
          // Number keys: select selection
          if (charKeyCode >= 49 && charKeyCode <= 57) {
            var n = charCode - 49;
            if (!this.candidates[page * 9 + n])
              break;

            this.workerManager.sendMessage('selectCandidate',
                                         this.candidates[page * 9 + n]);
          }
          break;
      }

      // No key should be handled by others in this mode.
      return true;
    }

    // Entering candidate selection mode with down arrow
    if (keyCode === 40 && this.candidates.length) {
      this.setCandidateSelectionMode(true);
      return true;
    }

    // non-printable keys shouldn't be handled by IME engine
    // if nothing is displayed presently.
    if (!charCode && !this.candidates.length && !this.pendingsymbols)
      return false;

    var code = symbolCode || charCode;
    // IME engine is only responsive to backspace and enter keyCodes,
    if (keyCode === 8 || keyCode === 13) {
      code = keyCode;
    }

    // other non-printable keys (charCode = 0) is meaningless to IME engine.
    if (!code)
      return false;

    this.workerManager.sendMessage('handleKeyEvent', code);

    return true;
  }
};
IMEFrontend.init();
<commit_msg>Convert IMEFrontend to constructor function<commit_after>'use strict';

var _ = require('sdk/l10n').get;
var Widget = require('sdk/widget').Widget;
var Hotkey = require('sdk/hotkeys').Hotkey;
var getFocusedElement = require('window/utils').getFocusedElement;

var debug = require('./debug').debug;

var KeyMonitor = require('./key-monitor').KeyMonitor;
var IMEOutput = require('./ime-output').IMEOutput;
var IMEWorkerManager = require('./ime-worker-manager').IMEWorkerManager;
var IMEDisplayManager = require('./ime-display-manager').IMEDisplayManager;

var IMEFrontend = function IMEFrontend() {
  this.active = false;
  this.inputActive = false;

  this.candidateSelectionMode = false;

  this.pendingsymbols = '';
  this.candidates = [];
  this.candidatePage = 0;

  // Show an widget
  this.widget = Widget({
    id: 'jszhuyin-indicator',
    label: _('JSZhuyin IME'),
    content: _('A')
  });

  // Register a hot key for toggling
  Hotkey({
    combo: this.hotkeyCombo,
    onPress: this.toggle.bind(this)
  });

  this.keyMonitor = new KeyMonitor(this);
  this.workerManager = new IMEWorkerManager(this);
  this.displayManager = new IMEDisplayManager(this);
  this.output = new IMEOutput();
};

IMEFrontend.prototype = {
  // XXX: make this configable
  hotkeyCombo: 'accel-alt-1',

  toggle: function if_toggle() {
    debug('[if/toggle]');
    if (!this.active) {
      this.start();
    } else {
      this.stop();
    }
  },

  start: function if_start() {
    if (this.active)
      return;

    debug('[if/start]');
    this.active = true;

    this.widget.content = 'ㄅ';

    this.displayManager.start();
    this.keyMonitor.start();
    this.workerManager.start();
  },

  stop: function if_stop() {
    if (!this.active)
      return;

    debug('[if/stop]');
    this.active = false;

    this.widget.content = 'A';
    this.stopInput();

    this.displayManager.start();
    this.keyMonitor.stop();
    this.workerManager.stop();
  },

  updateInput: function if_updateInput() {
    debug('[if/updateInput]');
    var focusedElement = getFocusedElement();
    if (this.output.canHandle(focusedElement)) {
      this.startInput(focusedElement);
    } else {
      this.stopInput();
    }
  },

  startInput: function if_startInput(focusedElement) {
    debug('[if/startInput]');
    this.inputActive = true;

    this.output.setFocusedElement(focusedElement);
  },

  stopInput: function if_stopInput() {
    debug('[if/stopInput]');
    if (!this.inputActive)
      return;

    this.inputActive = false;

    this.candidateSelectionMode = false;

    this.pendingsymbols = '';
    this.candidates = [];
    this.candidatePage = 0;
    this.toggleIMEDisplay();

    this.output.finishComposition('');
    this.output.setFocusedElement(null);
    this.workerManager.sendMessage('handleKeyEvent', 0x1b /* ESCAPE */);
  },

  setCandidateSelectionMode: function if_setCandidateSelectionMode(mode) {
    this.displayManager.sendMessage('candidateselectionmode', mode);
    this.candidateSelectionMode = mode;
  },

  toggleIMEDisplay: function if_toggleIMEDisplay() {
    if (this.pendingsymbols || this.candidates.length) {
      this.displayManager.show(getFocusedElement());
      this.keyMonitor.blockKeyUpDownEvent = true;
    } else if (this.displayManager.isShowing()) {
      this.displayManager.hide();
      this.keyMonitor.blockKeyUpDownEvent = false;
    }
  },

  handleWorkerMessage: function if_handleWorkerResult(name, data) {
    switch (name) {
      case 'compositionupdate':
        if (!this.inputActive)
          return;

        this.pendingsymbols = data;
        this.output.setComposition(data);
        this.toggleIMEDisplay();
        break;

      case 'candidateschange':
        if (!this.inputActive)
          return;

        this.candidates = data;
        this.candidatePage = 0;
        this.displayManager.sendMessage('candidates', data);
        this.toggleIMEDisplay();
        if (!this.candidates.length && this.candidateSelectionMode) {
          this.setCandidateSelectionMode(false);
        }
        break;

      case 'compositionend':
        this.output.finishComposition(data);
        break;
    }
  },

  handleDisplayMessage: function if_handleDisplayMessage(name, data) {
    switch (name) {
      case 'select':
        this.workerManager.sendMessage('selectCandidate', data);
        break;
    }
  },

  handleKeyEvent: function if_handleKeyEvent(keyCode, charCode, symbolCode) {
    this.updateInput();
    if (!this.inputActive)
      return false;

    // escape key: stop input mode immediately
    if (keyCode === 27) {
      this.stopInput();
      return true;
    }

    if (this.candidateSelectionMode) {
      // A non-printable character will come with charCode = 0,
      // let's squeeze these two code into one variable to simplify the logic.
      var charKeyCode = charCode || keyCode;

      var page = this.candidatePage;

      switch (charKeyCode) {
        case 8: // Backspace key: leave selection mode
          this.setCandidateSelectionMode(false);

          // IME engine will need to handle this bug too
          if (this.pendingsymbols) {
            // Let engine handles backspace
            this.workerManager.sendMessage('handleKeyEvent', keyCode);
          } else {
            // Let default handing to run instead.
            // return false;
            // ... or, remove the selection panel altogether w/o deleting
            // text that is sent?
            this.stopInput();
          }
          break;

        case 13: // Enter key: select 1st selection of the page
          if (!this.candidates[page * 9])
            break;

          this.workerManager.sendMessage('selectCandidate', this.candidates[page * 9]);
          break;

        case 37: // Left arrow key: flip candidate selection page
          if (page === 0)
            break;

          page = this.candidatePage -= 1;
          this.displayManager.sendMessage('candidateselectionpage', page);
          break;

        case 38: // Up arrow key: leaving candidate selection mode
          if (page !== 0) {
            page = 0;
            this.displayManager.sendMessage('candidateselectionpage', page);
          }

          this.setCandidateSelectionMode(false);
          break;

        case 39: // Right arrow key: flip candidate selection page
          if ((page + 1) * 9 >= this.candidates.length)
            break;

          page = this.candidatePage += 1;
          this.displayManager.sendMessage('candidateselectionpage', page);
          break;

        default:
          // Number keys: select selection
          if (charKeyCode >= 49 && charKeyCode <= 57) {
            var n = charCode - 49;
            if (!this.candidates[page * 9 + n])
              break;

            this.workerManager.sendMessage('selectCandidate',
                                         this.candidates[page * 9 + n]);
          }
          break;
      }

      // No key should be handled by others in this mode.
      return true;
    }

    // Entering candidate selection mode with down arrow
    if (keyCode === 40 && this.candidates.length) {
      this.setCandidateSelectionMode(true);
      return true;
    }

    // non-printable keys shouldn't be handled by IME engine
    // if nothing is displayed presently.
    if (!charCode && !this.candidates.length && !this.pendingsymbols)
      return false;

    var code = symbolCode || charCode;
    // IME engine is only responsive to backspace and enter keyCodes,
    if (keyCode === 8 || keyCode === 13) {
      code = keyCode;
    }

    // other non-printable keys (charCode = 0) is meaningless to IME engine.
    if (!code)
      return false;

    this.workerManager.sendMessage('handleKeyEvent', code);

    return true;
  }
};

exports.IMEFrontend = IMEFrontend;

// Bootstrap
exports.main = function main(options, callbacks) {
  new IMEFrontend();
};
<|endoftext|>


<commit_before>import {fromRange, toRange} from '../src'

describe('textPosition', () => {
  before(() => fixture.setBase('test/fixtures'))
  beforeEach(() => fixture.load('test.html'))
  afterEach(() => fixture.cleanup())

  describe('fromRange', () => {
    it('requires a root argument', () => {
      let construct = () => fromRange()
      assert.throws(construct, 'required parameter')
    })

    it('requires a range argument', () => {
      let construct = () => fromRange(fixture.el)
      assert.throws(construct, 'required parameter')
    })

    it('can describe a whole, single text node', () => {
      let root = fixture.el
      let range = document.createRange()
      let codeNode = root.querySelector('code')
      let textNode = codeNode.childNodes[0]
      range.selectNodeContents(textNode)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'commodo vitae')
    })

    it('can describe part of a single text node', () => {
      let root = fixture.el
      let range = document.createRange()
      let codeNode = root.querySelector('code')
      let textNode = codeNode.childNodes[0]
      range.setStart(textNode, 5)
      range.setEnd(textNode, 12)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'do vita')
    })

    it('can describe a range from one text node to another', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let emTextNode = emNode.childNodes[0]
      let codeNode = root.querySelector('code')
      let codeTextNode = codeNode.childNodes[0]
      range.setStart(emTextNode, 7)
      range.setEnd(codeTextNode, 7)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a whole, single element', () => {
      let root = fixture.el
      let range = document.createRange()
      let node = root.querySelector('code')
      range.selectNodeContents(node)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'commodo vitae')
    })

    it('can describe a range between elements', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let codeNode = root.querySelector('code')
      range.setStartBefore(emNode)
      range.setEndAfter(codeNode)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'Aenean ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo vitae',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a range between an element and a text node', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let codeNode = root.querySelector('code')
      let codeTextNode = codeNode.childNodes[0]
      range.setStartBefore(emNode)
      range.setEnd(codeTextNode, 7)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'Aenean ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a range between a text node and an element', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let emTextNode = emNode.childNodes[0]
      let codeNode = root.querySelector('code')
      range.setStart(emTextNode, 7)
      range.setEndAfter(codeNode, 7)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo vitae',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a range starting at an empty element', () => {
      let root = fixture.el
      let range = document.createRange()
      let hrEl = root.querySelector('hr')
      range.setStart(hrEl, 0)
      range.setEnd(hrEl.nextSibling.firstChild, 16)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'Praesent dapibus')
    });

    it('can describe a range ending at an empty element', () => {
      let root = fixture.el
      let range = document.createRange()
      let hrEl = root.querySelector('hr')
      let prevText = hrEl.previousSibling.lastChild
      range.setStart(prevText, prevText.textContent.length - 9)
      range.setEnd(hrEl, 0)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'Ut felis.')
    });

    it('can describe a range beginning at the end of a non-empty element', () => {
      let root = fixture.el
      let range = document.createRange()
      let strongEl = root.querySelector('strong')
      range.setStart(strongEl, 1)
      range.setEnd(strongEl.nextSibling, 9)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, ' senectus')
    });

    it('can describe a collapsed range', () => {
      let root = fixture.el
      let range = document.createRange()
      let strongEl = root.querySelector('strong')
      range.setStart(strongEl.firstChild, 10)
      range.setEnd(strongEl.firstChild, 5)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, '')
    });
  })

  describe('toRange', () => {
    it('requires a root argument', () => {
      let construct = () => toRange()
      assert.throws(construct, 'required parameter')
    })

    it('returns a range selecting a whole text node', () => {
      let root = fixture.el
      let expected = 'commodo vitae'
      let start = root.textContent.indexOf(expected)
      let end = start + expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns a range selecting part of a text node', () => {
      let root = fixture.el
      let expected = 'do vit'
      let start = root.textContent.indexOf(expected)
      let end = start + expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns a range selecting part of multiple text nodes', () => {
      let root = fixture.el
      let expected = 'do vitae, ornare'
      let start = root.textContent.indexOf(expected)
      let end = start + expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('defaults to a collapsed range', () => {
      let range = toRange(fixture.el)
      assert.isTrue(range.collapsed)
    })

    it('returns a range selecting the first text of the root element', () => {
      let root = fixture.el
      let expected = 'Pellentesque'
      let start = 0
      let end = expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns a range selecting the last text of the root element', () => {
      let root = fixture.el
      let expected = 'erat.'
      let end = root.textContent.length
      let start = end - 5
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns an empty range selecting the end of the root element', () => {
      let root = fixture.el
      let end = root.textContent.length
      let range = toRange(root, {start: end, end})
      let text = range.toString()
      assert.equal(text, '')
    })

    it('throws an error if the start offset is out of range', () => {
      let root = fixture.el
      assert.throws(() => {
        let start = 10000
        let end = start + 1
        toRange(root, {start, end})
      }, 'Start offset of position selector is out of range')
    })

    it('throws an error if the end offset is out of range', () => {
      let root = fixture.el
      assert.throws(() => {
        let start = 0
        let end = 10000
        toRange(root, {start, end})
      }, 'End offset of position selector is out of range')
    })

    it('handles an empty root element', () => {
      let root = document.createElement('div');
      assert.throws(() => {
        toRange(root, {start:0, end: 0})
      }, 'Start offset of position selector is out of range');
    })

    it('handles a root element with an empty text node', () => {
      let root = document.createElement('div');
      root.appendChild(document.createTextNode(''))
      let range = toRange(root, {start:0, end: 0})
      assert.equal(range.toString(), '')
    })
  })
})
<commit_msg>Add a test for what happens when `end` is less than `start`<commit_after>import {fromRange, toRange} from '../src'

describe('textPosition', () => {
  before(() => fixture.setBase('test/fixtures'))
  beforeEach(() => fixture.load('test.html'))
  afterEach(() => fixture.cleanup())

  describe('fromRange', () => {
    it('requires a root argument', () => {
      let construct = () => fromRange()
      assert.throws(construct, 'required parameter')
    })

    it('requires a range argument', () => {
      let construct = () => fromRange(fixture.el)
      assert.throws(construct, 'required parameter')
    })

    it('can describe a whole, single text node', () => {
      let root = fixture.el
      let range = document.createRange()
      let codeNode = root.querySelector('code')
      let textNode = codeNode.childNodes[0]
      range.selectNodeContents(textNode)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'commodo vitae')
    })

    it('can describe part of a single text node', () => {
      let root = fixture.el
      let range = document.createRange()
      let codeNode = root.querySelector('code')
      let textNode = codeNode.childNodes[0]
      range.setStart(textNode, 5)
      range.setEnd(textNode, 12)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'do vita')
    })

    it('can describe a range from one text node to another', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let emTextNode = emNode.childNodes[0]
      let codeNode = root.querySelector('code')
      let codeTextNode = codeNode.childNodes[0]
      range.setStart(emTextNode, 7)
      range.setEnd(codeTextNode, 7)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a whole, single element', () => {
      let root = fixture.el
      let range = document.createRange()
      let node = root.querySelector('code')
      range.selectNodeContents(node)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'commodo vitae')
    })

    it('can describe a range between elements', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let codeNode = root.querySelector('code')
      range.setStartBefore(emNode)
      range.setEndAfter(codeNode)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'Aenean ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo vitae',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a range between an element and a text node', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let codeNode = root.querySelector('code')
      let codeTextNode = codeNode.childNodes[0]
      range.setStartBefore(emNode)
      range.setEnd(codeTextNode, 7)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'Aenean ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a range between a text node and an element', () => {
      let root = fixture.el
      let range = document.createRange()
      let emNode = root.querySelector('em')
      let emTextNode = emNode.childNodes[0]
      let codeNode = root.querySelector('code')
      range.setStart(emTextNode, 7)
      range.setEndAfter(codeNode, 7)
      let anchor = fromRange(root, range)
      let {start, end} = anchor
      let text = root.textContent.substr(start, end - start)
      let expected = [
        'ultricies mi vitae est.',
        ' Mauris placerat eleifend\n  leo. Quisque sit amet est',
        ' et sapien ullamcorper pharetra. Vestibulum erat\n',
        '  wisi, condimentum sed, commodo vitae',
      ].join('')
      assert.equal(text, expected)
    })

    it('can describe a range starting at an empty element', () => {
      let root = fixture.el
      let range = document.createRange()
      let hrEl = root.querySelector('hr')
      range.setStart(hrEl, 0)
      range.setEnd(hrEl.nextSibling.firstChild, 16)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'Praesent dapibus')
    });

    it('can describe a range ending at an empty element', () => {
      let root = fixture.el
      let range = document.createRange()
      let hrEl = root.querySelector('hr')
      let prevText = hrEl.previousSibling.lastChild
      range.setStart(prevText, prevText.textContent.length - 9)
      range.setEnd(hrEl, 0)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, 'Ut felis.')
    });

    it('can describe a range beginning at the end of a non-empty element', () => {
      let root = fixture.el
      let range = document.createRange()
      let strongEl = root.querySelector('strong')
      range.setStart(strongEl, 1)
      range.setEnd(strongEl.nextSibling, 9)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, ' senectus')
    });

    it('can describe a collapsed range', () => {
      let root = fixture.el
      let range = document.createRange()
      let strongEl = root.querySelector('strong')
      range.setStart(strongEl.firstChild, 10)
      range.setEnd(strongEl.firstChild, 5)
      let {start, end} = fromRange(root, range)
      let text = root.textContent.substr(start, end - start)
      assert.equal(text, '')
    });
  })

  describe('toRange', () => {
    it('requires a root argument', () => {
      let construct = () => toRange()
      assert.throws(construct, 'required parameter')
    })

    it('returns a range selecting a whole text node', () => {
      let root = fixture.el
      let expected = 'commodo vitae'
      let start = root.textContent.indexOf(expected)
      let end = start + expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns a range selecting part of a text node', () => {
      let root = fixture.el
      let expected = 'do vit'
      let start = root.textContent.indexOf(expected)
      let end = start + expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns a range selecting part of multiple text nodes', () => {
      let root = fixture.el
      let expected = 'do vitae, ornare'
      let start = root.textContent.indexOf(expected)
      let end = start + expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('defaults to a collapsed range', () => {
      let range = toRange(fixture.el)
      assert.isTrue(range.collapsed)
    })

    it('returns a range selecting the first text of the root element', () => {
      let root = fixture.el
      let expected = 'Pellentesque'
      let start = 0
      let end = expected.length
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns a range selecting the last text of the root element', () => {
      let root = fixture.el
      let expected = 'erat.'
      let end = root.textContent.length
      let start = end - 5
      let range = toRange(root, {start, end})
      let text = range.toString()
      assert.equal(text, expected)
    })

    it('returns an empty range selecting the end of the root element', () => {
      let root = fixture.el
      let end = root.textContent.length
      let range = toRange(root, {start: end, end})
      let text = range.toString()
      assert.equal(text, '')
    })

    it('throws an error if the start offset is out of range', () => {
      let root = fixture.el
      assert.throws(() => {
        let start = 10000
        let end = start + 1
        toRange(root, {start, end})
      }, 'Start offset of position selector is out of range')
    })

    it('throws an error if the end offset is out of range', () => {
      let root = fixture.el
      assert.throws(() => {
        let start = 0
        let end = 10000
        toRange(root, {start, end})
      }, 'End offset of position selector is out of range')
    })

    it('handles an empty root element', () => {
      let root = document.createElement('div');
      assert.throws(() => {
        toRange(root, {start:0, end: 0})
      }, 'Start offset of position selector is out of range');
    })

    it('handles a root element with an empty text node', () => {
      let root = document.createElement('div');
      root.appendChild(document.createTextNode(''))
      let range = toRange(root, {start:0, end: 0})
      assert.equal(range.toString(), '')
    })

    it('handles an `end` offset less than the `start` offset', () => {
      let root = fixture.el
      let expected = 'do vit'
      let start = root.textContent.indexOf(expected)
      let end = start + expected.length
      let range = toRange(root, {start: end, end: start})
      let text = range.toString()

      // This case could reasonably throw or simply return a collapsed range.
      // It returns a collapsed range as that seems like it would be more
      // convenient for the caller.
      assert.equal(text, '')
    })
  })
})
<|endoftext|>


<commit_before>var ax = 0, ay = 0,
vx = 0, vy = 0, windowx = window.innerWidth,
windowy = window.innerHeight, centerx = windowx / 2,
centery = windowy / 2;

var lastTime = new Date().getTime();

window.ondevicemotion = function(e) {
  ax = e.accelerationIncludingGravity.x * 300; //acceleration along x axis
  ay = e.accelerationIncludingGravity.y * -300; //acceleration along y axis
  vx = vx + ax;
  vy = vy + ay;
  var now = new Date().getTime();
  document.getElementById('info').innerHTML = 1000 / (now - lastTime);
  lastTime = now;
};

var main = {
  preload: function() {
    // This function will be executed at the beginning
    // That's where we load the game's assets
  game.load.image('ball', 'assets/ball.png', 400, 400);
  game.stage.backgroundColor = '#FFFFFF';

  },

  create: function() {

  game.physics.startSystem(Phaser.Physics.ARCADE);

  //this is the player ball
  playerBall = game.add.sprite(centerx, centery, 'ball');
  game.physics.enable(playerBall, Phaser.Physics.ARCADE);
  playerBall.body.collideWorldBounds = true;
  playerBall.body.checkCollision = true;
  playerBall.body.bounce.set(0.8);
  playerBall.scale.setTo(0.5,0.5);

  //adding an enemy ball to test collision
  enemyBall = game.add.sprite(centerx, centery / 2, 'ball');
  game.physics.enable(enemyBall, Phaser.Physics.ARCADE);
  enemyBall.scale.setTo(0.2,0.2);
  enemyBall.body.checkCollision = true;
  enemyBall.body.bounce.set(1,1);
  enemyBall.body.immovable = true;

  },

  update: function() {
    // This function is called 60 times per second
    // It contains the game's logic
    playerBall.body.acceleration.setTo(ax,ay);
    game.physics.arcade.collide(playerBall, enemyBall);
  }

};

// Initialize Phaser, and start our 'main' state
var game = new Phaser.Game(windowx, windowy, Phaser.AUTO, 'ballerDiv');
game.state.add('main', main);
game.state.start('main');<commit_msg>created a group of enemy balls which can collide into each other.<commit_after>var ax = 0, ay = 0,
vx = 0, vy = 0, windowx = window.innerWidth,
windowy = window.innerHeight, centerx = windowx / 2,
centery = windowy / 2;

var lastTime = new Date().getTime();

window.ondevicemotion = function(e) {
  ax = e.accelerationIncludingGravity.x * 300; //acceleration along x axis
  ay = e.accelerationIncludingGravity.y * -300; //acceleration along y axis
  vx = vx + ax;
  vy = vy + ay;
  var now = new Date().getTime();
  document.getElementById('info').innerHTML = 1000 / (now - lastTime);
  lastTime = now;
};

var enemies;

var main = {
  preload: function() {
    // This function will be executed at the beginning
    // That's where we load the game's assets
    game.load.image('ball', 'assets/ball.png', 400, 400);
    game.stage.backgroundColor = '#FFFFFF';

  },

  create: function() {

    game.physics.startSystem(Phaser.Physics.ARCADE);

    //this is the player ball
    playerBall = game.add.sprite(centerx, centery, 'ball');
    game.physics.enable(playerBall, Phaser.Physics.ARCADE);
    playerBall.body.collideWorldBounds = true;
    playerBall.body.checkCollision = true;
    playerBall.body.bounce.set(0.9);
    playerBall.scale.setTo(0.3,0.3);

    //adding an enemy ball to test collision
      // enemyBall = game.add.sprite(centerx, centery / 2, 'ball');
      // game.physics.enable(enemyBall, Phaser.Physics.ARCADE);
      // enemyBall.scale.setTo(0.2,0.2);
      // enemyBall.body.checkCollision = true;
      // enemyBall.body.bounce.set(1,1);
      // enemyBall.body.immovable = true;

    // create a bunch of randomly moving balls which bounce
    var enemy;

    enemies = game.add.group();
    enemies.enableBody = true;
    enemies.physicsBodyType = Phaser.Physics.ARCADE;

    for (var x = 0; x < 30; x++) {
      enemy = enemies.create(game.world.randomX, game.world.randomY, 'ball');
      enemy.body.bounce.set(0.9);
      var rand = game.rnd.realInRange(5, 50);
      enemy.body.velocity.setTo(rand, rand);
      enemy.body.collideWorldBounds = true;
      enemy.scale.setTo(0.1,0.1);
    }

  },

  update: function() {
    // This function is called 60 times per second
    // It contains the game's logic
    playerBall.body.acceleration.setTo(ax,ay);
    game.physics.arcade.collide(playerBall, enemies);
    game.physics.arcade.collide(enemies, enemies);
  }

};

// Initialize Phaser, and start our 'main' state
var game = new Phaser.Game(windowx, windowy, Phaser.AUTO, 'ballerDiv');
game.state.add('main', main);
game.state.start('main');<|endoftext|>


<commit_before>/*!
EmberUI (c) 2014 Jaco Joubert
License: https://github.com/emberui/emberui/blob/master/LICENSE
*/

import EuiButton from './components/eui-button';
import EuiButtonTemplate from './templates/eui-button';

import EuiCheckbox from './components/eui-checkbox';
import EuiCheckboxTemplate from './templates/eui-checkbox';

import EuiDropbutton from './components/eui-dropbutton';
import EuiDropbuttonTemplate from './templates/eui-dropbutton';

import EuiInput from './components/eui-input';
import EuiInputTemplate from './templates/eui-input';

import EuiModal from './components/eui-modal';
import EuiModalTemplate from './templates/eui-modal';

import EuiPoplist from './components/eui-poplist';
import EuipoplistTemplate from './templates/eui-poplist';

import EuiSelect from './components/eui-select';
import EuiSelectTemplate from './templates/eui-select';

import EuiTextarea from './components/eui-textarea';
import EuiTextareaTemplate from './templates/eui-textarea';

Application.initializer({
  name: 'ember-ui',

  initialize: function(container) {
    container.register('template:components/eui-button', EuiButtonTemplate);
    container.register('component:eui-button', EuiButtonComponent);

    container.register('template:components/eui-checkbox', EuiCheckboxTemplate);
    container.register('component:eui-checkbox', EuiCheckboxComponent);

    container.register('template:components/eui-dropbutton', EuiDropbuttonTemplate);
    container.register('component:eui-dropbutton', EuiDropbuttonComponent);

    container.register('template:components/eui-input', EuiInputTemplate);
    container.register('component:eui-input', EuiInputComponent);

    container.register('template:components/eui-modal', EuiModalTemplate);
    container.register('component:eui-modal', EuiModalComponent);

    container.register('template:components/eui-poplist', EuiPoplistTemplate);
    container.register('component:eui-poplist', EuiPoplistComponent);

    container.register('template:components/eui-select', EuiSelectTemplate);
    container.register('component:eui-select', EuiSelectComponent);

    container.register('template:components/eui-textarea', EuiTextareaTemplate);
    container.register('component:eui-textarea', EuiTextareaComponent);
  }
});

export {
  EuiButtonComponent,
  EuiCheckboxComponent,
  EuiDropbuttonComponent,
  EuiInputComponent,
  EuiModalComponent,
  EuiPoplistComponent,
  EuiSelectComponent,
  EuiTextareaComponent
};
<commit_msg>register missing template, remove - from application name, fix typo in import<commit_after>/*!
EmberUI (c) 2014 Jaco Joubert
License: https://github.com/emberui/emberui/blob/master/LICENSE
*/

import EuiButton from './components/eui-button';
import EuiButtonTemplate from './templates/eui-button';

import EuiCheckbox from './components/eui-checkbox';
import EuiCheckboxTemplate from './templates/eui-checkbox';

import EuiDropbutton from './components/eui-dropbutton';
import EuiDropbuttonTemplate from './templates/eui-dropbutton';

import EuiInput from './components/eui-input';
import EuiInputTemplate from './templates/eui-input';

import EuiModal from './components/eui-modal';
import EuiModalTemplate from './templates/eui-modal';

import EuiPoplist from './components/eui-poplist';
import EuiPoplistTemplate from './templates/eui-poplist';
import EuiPoplistOptionTemplate from './templates/eui-poplist-option';

import EuiSelect from './components/eui-select';
import EuiSelectTemplate from './templates/eui-select';

import EuiTextarea from './components/eui-textarea';
import EuiTextareaTemplate from './templates/eui-textarea';

Application.initializer({
  name: 'emberui',

  initialize: function(container) {
    container.register('template:components/eui-button', EuiButtonTemplate);
    container.register('component:eui-button', EuiButtonComponent);

    container.register('template:components/eui-checkbox', EuiCheckboxTemplate);
    container.register('component:eui-checkbox', EuiCheckboxComponent);

    container.register('template:components/eui-dropbutton', EuiDropbuttonTemplate);
    container.register('component:eui-dropbutton', EuiDropbuttonComponent);

    container.register('template:components/eui-input', EuiInputTemplate);
    container.register('component:eui-input', EuiInputComponent);

    container.register('template:components/eui-modal', EuiModalTemplate);
    container.register('component:eui-modal', EuiModalComponent);

    container.register('template:components/eui-poplist', EuiPoplistTemplate);
    container.register('template:components/eui-poplist-opion', EuiPoplistOptionTemplate);
    container.register('component:eui-poplist', EuiPoplistComponent);

    container.register('template:components/eui-select', EuiSelectTemplate);
    container.register('component:eui-select', EuiSelectComponent);

    container.register('template:components/eui-textarea', EuiTextareaTemplate);
    container.register('component:eui-textarea', EuiTextareaComponent);
  }
});

export {
  EuiButtonComponent,
  EuiCheckboxComponent,
  EuiDropbuttonComponent,
  EuiInputComponent,
  EuiModalComponent,
  EuiPoplistComponent,
  EuiSelectComponent,
  EuiTextareaComponent
};
<|endoftext|>


<commit_before>$(document).ready(function () {
    /* Cookies */
    var distrib = Cookies.get('distrib');
    var search = Cookies.get('engine');

    /* Change colors, logo & links */
    function changeDistrib() {
        distrib = Cookies.get('distrib');

        var colors = {
            debian: "a80030",
            ubuntu: "dd4814",
            fedora: "374d7b",
            elementaryos: "44a2e9",
            archlinux: "1793d1",
            linuxmint: "7dbe3b",
            maegia: "262f45"
        };
        var sites = {
            debian: "https://www.debian.org",
            ubuntu: "http://www.ubuntu.com",
            fedora: "https://fedoraproject.org",
            elementaryos: "http://elementaryos.org",
            archlinux: "https://www.archlinux.org",
            linuxmint: "http://www.linuxmint.com",
            maegia: "https://www.mageia.org"
        };
        var docs = {
            debian: "https://www.debian.org/doc",
            ubuntu: "http://doc.ubuntu-fr.org",
            fedora: "http://doc.fedora-fr.org/wiki",
            elementaryos: "http://www.elementaryos-fr.org/documentation",
            archlinux: "https://wiki.archlinux.fr",
            linuxmint: "http://www.linuxmint.com/documentation.php",
            maegia: "https://www.mageia.org/fr/doc"
        };

        $("#logo-img").attr("src", "img/" + distrib + "-logo.png");

        $("#search").css("background", "#" + colors[distrib]);
        $("#navbar ul li a").css("color", "#" + colors[distrib]);

        $(".site").attr("href", sites[distrib]).text("Site officiel");
        $(".doc").attr("href", docs[distrib]).text("Documentation");
    }

    /* Distribution cookie */
    if(distrib == null) {
        Cookies.set('distrib', 'ubuntu', { expires: 365, path: '/' });
    }
    changeDistrib();

    /* Choose distribution */
    $(".distribution").click(function () {
        var id_distrib = $(this).attr("id");
        Cookies.set('distrib', id_distrib, { expires: 365, path: '/' });
        $("#options").slideToggle();
        changeDistrib();
    });

    /* Chevrons */
    $(".chevrons").click(function () {
        $("#options").slideToggle();
    });
    $(".chevrons2").click(function () {
        $("#options").slideToggle();
    });

    /* Search engine */
    var search_engines = {
        bing: "https://www.bing.com/search?q=",
        yahoo: "https://fr.search.yahoo.com/search?p=",
        google: "https://www.google.com/search?q=",
        duckduckgo: "https://duckduckgo.com/?q=test",
        qwant: "https://www.qwant.com/?q=",
        ecosia: "http://www.ecosia.org/search?q="
    };

    /* Test if cookie is defined */
    if (search === undefined) {
        Cookies.set('engine', 'duckduckgo', { expires: 365, path: '/' });
        $("form").attr("action", search_engines["duckduckgo"]);
        $("#choose-engine").addClass("duckduckgo");
    } else {
        $("form").attr("action", search_engines[search]);
        $("#choose-engine").addClass(search);
    }

    /* Open popup */
    $("#choose-engine").click(function () {
        $("#engines").slideToggle();
    });

    /* Close popup */
    $(".button-cancel").click(function () {
        $("#engines").slideToggle();
    });

    /* Choose search engine */
    $(".button-engine").click(function () {
        var engine_id = $(this).attr("id");

        $("form").attr("action", search_engines[engine_id]);
        $("#choose-engine").removeClass().addClass(engine_id);
        Cookies.set('engine', engine_id, { expires: 365, path: '/' });

        $("#engines").slideToggle();
    });
});
<commit_msg>Sort search engines and distribs<commit_after>$(document).ready(function () {
    /* Cookies */
    var distrib = Cookies.get('distrib');
    var search = Cookies.get('engine');

    /* Change colors, logo & links */
    function changeDistrib() {
        distrib = Cookies.get('distrib');

        var colors = {
            archlinux: "1793d1",
            debian: "a80030",
            elementaryos: "44a2e9",
            fedora: "374d7b",
            linuxmint: "7dbe3b",
            maegia: "262f45",
            ubuntu: "dd4814"
        };
        var sites = {
            archlinux: "https://www.archlinux.org",
            debian: "https://www.debian.org",
            elementaryos: "http://elementaryos.org",
            fedora: "https://fedoraproject.org",
            linuxmint: "http://www.linuxmint.com",
            maegia: "https://www.mageia.org",
            ubuntu: "http://www.ubuntu.com"
        };
        var docs = {
            archlinux: "https://wiki.archlinux.fr",
            debian: "https://www.debian.org/doc",
            elementaryos: "http://www.elementaryos-fr.org/documentation",
            fedora: "http://doc.fedora-fr.org/wiki",
            linuxmint: "http://www.linuxmint.com/documentation.php",
            maegia: "https://www.mageia.org/fr/doc",
            ubuntu: "http://doc.ubuntu-fr.org"
        };

        $("#logo-img").attr("src", "img/" + distrib + "-logo.png");

        $("#search").css("background", "#" + colors[distrib]);
        $("#navbar ul li a").css("color", "#" + colors[distrib]);

        $(".site").attr("href", sites[distrib]).text("Site officiel");
        $(".doc").attr("href", docs[distrib]).text("Documentation");
    }

    /* Distribution cookie */
    if(distrib == null) {
        Cookies.set('distrib', 'ubuntu', { expires: 365, path: '/' });
    }
    changeDistrib();

    /* Choose distribution */
    $(".distribution").click(function () {
        var id_distrib = $(this).attr("id");
        Cookies.set('distrib', id_distrib, { expires: 365, path: '/' });
        $("#options").slideToggle();
        changeDistrib();
    });

    /* Chevrons */
    $(".chevrons").click(function () {
        $("#options").slideToggle();
    });
    $(".chevrons2").click(function () {
        $("#options").slideToggle();
    });

    /* Search engine */
    var search_engines = {
        bing: "https://www.bing.com/search?q=",
        duckduckgo: "https://duckduckgo.com/?q=test",
        ecosia: "http://www.ecosia.org/search?q=",
        google: "https://www.google.com/search?q=",
        qwant: "https://www.qwant.com/?q=",
        yahoo: "https://fr.search.yahoo.com/search?p="
    };

    /* Test if cookie is defined */
    if (search === undefined) {
        Cookies.set('engine', 'duckduckgo', { expires: 365, path: '/' });
        $("form").attr("action", search_engines["duckduckgo"]);
        $("#choose-engine").addClass("duckduckgo");
    } else {
        $("form").attr("action", search_engines[search]);
        $("#choose-engine").addClass(search);
    }

    /* Open popup */
    $("#choose-engine").click(function () {
        $("#engines").slideToggle();
    });

    /* Close popup */
    $(".button-cancel").click(function () {
        $("#engines").slideToggle();
    });

    /* Choose search engine */
    $(".button-engine").click(function () {
        var engine_id = $(this).attr("id");

        $("form").attr("action", search_engines[engine_id]);
        $("#choose-engine").removeClass().addClass(engine_id);
        Cookies.set('engine', engine_id, { expires: 365, path: '/' });

        $("#engines").slideToggle();
    });
});
<|endoftext|>


<commit_before>'use strict';
const Shield = require('./Shield.js');
const wrapRelations = require('./wrapRelations.js');
const _ = require('lodash');
const joi = require('joi');
const internals = {
    models: {},
    acl: null,
    authConfig: []
}
;
/**
 * Shortcut to get auth configs that apply to a given model
 * @param {string} modelName is the name of the model
 * @return {array} an array of matching configs
 */
function getAuthConfigs(modelName) {
    return _.filter(internals.authConfig, function hasSameModelName(c) {
        return c.defaults.modelName === modelName;
    });
}

/**
 * Set an individual model on the internal scope after wrapping it with a shield
 * @param {bookshelfModel} Model is a bookshelf Model constructor
 * @return null;
 */
function setModel(Model, modelName) {
    let authConfigs;
    if (!internals.acl) {
        throw new Error('Attempt to shield model before setting acl');
    }

    if (!internals.authConfig.length) {
        throw new Error('Attempt to shield model before seting configs');
    }

    // raise shield around Model
    new Shield(Model, internals.acl);
    authConfigs = getAuthConfigs(modelName);
    _.each(authConfigs, Model.shield.addRules, Model.shield);
    internals.models[modelName] = Model;
}

/**
 * set internal models
 * @param {object} models is an object with modelName: Model key pairs
 * @return null
 */
function setModels(models) {
    _.each(models, setModel);
}

/**
 * set internal authConfig
 * @param {array} configs see Shield.js for config example
 * @return null
 */
function setAuthConfig(configs) {
    internals.authConfig = configs;
}

/**
 * set internal ACL
 * @param {object} acl is the ACL object (e.g. relations)
 * @return null
 */
function setAcl(acl) {
    internals.acl = wrapRelations(acl);
}

/**
 * Validate that the all inputs are properly specified
 */
function validate(options) {
    const schema = joi.object().keys({
        config: joi.array().min(_.keys(options.models).length).required(),
        acl: joi.object().required(),
        models: joi.object().required()
    });
    joi.assert(options, schema, 'Invalid Shield Options:');
    return true;
}

/**
 * Main initialization method
 * @param {object} options is an object with keys for:
 *   config: the authConfig detailing rules for each model
 *   models: an object containing modelName: Model key pairs
 *   acl: the Action Control List object containing methods for each context
 * @return {null} the shield internals are private
 */
function init(options) {
    validate(options);
    setAuthConfig(options.config);
    setAcl(options.acl);
    setModels(options.models);
}

module.exports = init;
<commit_msg>actually add squashed line...<commit_after>'use strict';
const Shield = require('./Shield.js');
const wrapRelations = require('./wrapRelations.js');
const _ = require('lodash');
const joi = require('joi');
const internals = {
    models: {},
    acl: null,
    authConfig: []
};

/**
 * Shortcut to get auth configs that apply to a given model
 * @param {string} modelName is the name of the model
 * @return {array} an array of matching configs
 */
function getAuthConfigs(modelName) {
    return _.filter(internals.authConfig, function hasSameModelName(c) {
        return c.defaults.modelName === modelName;
    });
}

/**
 * Set an individual model on the internal scope after wrapping it with a shield
 * @param {bookshelfModel} Model is a bookshelf Model constructor
 * @return null;
 */
function setModel(Model, modelName) {
    let authConfigs;
    if (!internals.acl) {
        throw new Error('Attempt to shield model before setting acl');
    }

    if (!internals.authConfig.length) {
        throw new Error('Attempt to shield model before seting configs');
    }

    // raise shield around Model
    new Shield(Model, internals.acl);
    authConfigs = getAuthConfigs(modelName);
    _.each(authConfigs, Model.shield.addRules, Model.shield);
    internals.models[modelName] = Model;
}

/**
 * set internal models
 * @param {object} models is an object with modelName: Model key pairs
 * @return null
 */
function setModels(models) {
    _.each(models, setModel);
}

/**
 * set internal authConfig
 * @param {array} configs see Shield.js for config example
 * @return null
 */
function setAuthConfig(configs) {
    internals.authConfig = configs;
}

/**
 * set internal ACL
 * @param {object} acl is the ACL object (e.g. relations)
 * @return null
 */
function setAcl(acl) {
    internals.acl = wrapRelations(acl);
}

/**
 * Validate that the all inputs are properly specified
 */
function validate(options) {
    const schema = joi.object().keys({
        config: joi.array().min(_.keys(options.models).length).required(),
        acl: joi.object().required(),
        models: joi.object().required()
    });
    joi.assert(options, schema, 'Invalid Shield Options:');
    return true;
}

/**
 * Main initialization method
 * @param {object} options is an object with keys for:
 *   config: the authConfig detailing rules for each model
 *   models: an object containing modelName: Model key pairs
 *   acl: the Action Control List object containing methods for each context
 * @return {null} the shield internals are private
 */
function init(options) {
    validate(options);
    setAuthConfig(options.config);
    setAcl(options.acl);
    setModels(options.models);
}

module.exports = init;
<|endoftext|>


<commit_before>"use strict";

describe("interfaces", function () {

    describe("gpf.interfaces.IUnknown", function () {

        it("exists", function () {
            assert("function" === typeof gpf.interfaces.IUnknown);
        });

        it("is an interface", function () {
            var exceptionCaught;
            try {
                var instance = new gpf.interfaces.IUnknown();
                assert(instance);
            } catch (e) {
                exceptionCaught = e;
            }
            assert(exceptionCaught instanceof gpf.Error.InterfaceConstructorFunction);
        });

    });

    describe("gpf.interfaces.isImplementedBy", function () {

        function TestRawClass () {}
        TestRawClass.prototype = {
            queryInterface: function (oneParameter) {
                return oneParameter;
            }
        };

        var TestGPFClass = gpf.define({
            $class: "TestGPFClass",
            queryInterface: function (oneParameter) {
                return oneParameter;
            }
        });

        it("validates literal objects (using interface constructor)", function () {
            assert(true === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, {
                queryInterface: function (oneParameter) {
                    return oneParameter;
                }
            }));
        });

        it("validates instances from a raw JavaScript class (using interface name)", function () {
            var obj = new TestRawClass();
            assert(true === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", obj));
        });

        it("validates a raw JavaScript class", function () {
            assert(true === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", TestRawClass));
        });

        it("validates instances from a GPF class", function () {
            var obj = new TestGPFClass();
            assert(true === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, obj));
        });

        it("validates a GPF class", function () {
            assert(true === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, TestGPFClass));
        });

        it("rejects member if not a method", function () {
            assert(false === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", {
                queryInterface: "Not a method"
            }));
        });

        it("rejects member if parameters count does not match (none)", function () {
            assert(false === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", {
                queryInterface: function () {}
            }));
        });

        it("rejects member if parameters count does not match (more)", function () {
            assert(false === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, {
                queryInterface: function (a, b, c) {
                    return a + b + c;
                }
            }));
        });

    });

});
<commit_msg>FIX #150<commit_after>"use strict";

describe("interfaces", function () {

    function _ignore () {}

    describe("gpf.interfaces.IUnknown", function () {

        it("exists", function () {
            assert("function" === typeof gpf.interfaces.IUnknown);
        });

        it("is an interface", function () {
            var exceptionCaught;
            try {
                var instance = new gpf.interfaces.IUnknown();
                assert(instance);
            } catch (e) {
                exceptionCaught = e;
            }
            assert(exceptionCaught instanceof gpf.Error.InterfaceConstructorFunction);
        });

    });

    describe("gpf.interfaces.isImplementedBy", function () {

        function TestRawClass () {}
        TestRawClass.prototype = {
            queryInterface: function (oneParameter) {
                return oneParameter;
            }
        };

        var TestGPFClass = gpf.define({
            $class: "TestGPFClass",
            queryInterface: function (oneParameter) {
                return oneParameter;
            }
        });

        it("validates literal objects (using interface constructor)", function () {
            assert(true === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, {
                queryInterface: function (oneParameter) {
                    return oneParameter;
                }
            }));
        });

        it("validates instances from a raw JavaScript class (using interface name)", function () {
            var obj = new TestRawClass();
            assert(true === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", obj));
        });

        it("validates a raw JavaScript class", function () {
            assert(true === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", TestRawClass));
        });

        it("validates instances from a GPF class", function () {
            var obj = new TestGPFClass();
            assert(true === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, obj));
        });

        it("validates a GPF class", function () {
            assert(true === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, TestGPFClass));
        });

        it("rejects member if not a method", function () {
            assert(false === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", {
                queryInterface: "Not a method"
            }));
        });

        it("rejects member if parameters count does not match (none)", function () {
            assert(false === gpf.interfaces.isImplementedBy("gpf.interfaces.IUnknown", {
                queryInterface: function () {}
            }));
        });

        it("rejects member if parameters count does not match (more)", function () {
            assert(false === gpf.interfaces.isImplementedBy(gpf.interfaces.IUnknown, {
                queryInterface: function (a, b, c) {
                    return a + b + c;
                }
            }));
        });

    });

    describe("gpf.interfaces.query", function () {

        function ITest () {}
        ITest.prototype.test = function (a, b) {
            return a + b;
        };

        it("returns the object if it implements the interface (using interface name)", function () {
            var obj = {
                queryInterface: function (oneParameter) {
                    return oneParameter;
                }
            };
            assert(obj === gpf.interfaces.query("gpf.interfaces.IUnknown", obj));
        });

        it("returns the object if it implements the interface (using interface specifier)", function () {
            var obj = {
                test: function (a, b) {
                    _ignore(a, b);
                }
            };
            assert(obj === gpf.interfaces.query(ITest, obj));
        });

        it("returns null if IUnknown is implemented but not the expected interface", function () {
            assert(null === gpf.interfaces.query(ITest, {
                queryInterface: function (oneParameter) {
                    _ignore(oneParameter);
                    return null; // Because this is the expected interface
                }
            }));
        });

        it("uses IUnknown to get the expected interface", function () {
            assert(null !== gpf.interfaces.query(ITest, {
                queryInterface: function (interfaceSpecifier) {
                    assert(interfaceSpecifier === ITest);
                    return {
                        test: function (a, b) {
                            _ignore(a, b);
                        }
                    };
                }
            }));
        });

        it("returns undefined if neither the expected interface or IUnknown are implemented", function () {
            assert(undefined === gpf.interfaces.query(ITest, {
                queryInterface: function () { // Not matching IUnknown
                    return null;
                }
            }));
        });

    });

});
<|endoftext|>