<commit_before>// Copyright 2012 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

goog.provide('goog.net.xpc.IframePollingTransportTest');
goog.setTestOnly('goog.net.xpc.IframePollingTransportTest');

goog.require('goog.Timer');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.functions');
goog.require('goog.net.xpc.CfgFields');
goog.require('goog.net.xpc.CrossPageChannel');
goog.require('goog.net.xpc.CrossPageChannelRole');
goog.require('goog.net.xpc.TransportTypes');
goog.require('goog.object');
goog.require('goog.testing.MockClock');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.recordFunction');

var mockClock = null;
var outerChannel = null;
var innerChannel = null;

function setUp() {
  mockClock = new goog.testing.MockClock(true /* opt_autoInstall */);

  // Create the peer windows.
  var outerPeerHostName = 'https://www.youtube.com';
  var outerPeerWindow = createMockPeerWindow(outerPeerHostName);

  var innerPeerHostName = 'https://www.google.com';
  var innerPeerWindow = createMockPeerWindow(innerPeerHostName);

  // Create the channels.
  outerChannel = createChannel(
      goog.net.xpc.CrossPageChannelRole.OUTER, 'test', outerPeerHostName,
      outerPeerWindow, innerPeerHostName, innerPeerWindow);
  innerChannel = createChannel(
      goog.net.xpc.CrossPageChannelRole.INNER, 'test', innerPeerHostName,
      innerPeerWindow, outerPeerHostName, outerPeerWindow);
}

function tearDown() {
  outerChannel.dispose();
  innerChannel.dispose();
  mockClock.uninstall();
}

/** Tests that connection happens normally and callbacks are invoked. */
function testConnect() {
  var outerConnectCallback = goog.testing.recordFunction();
  var innerConnectCallback = goog.testing.recordFunction();

  // Connect the two channels.
  outerChannel.connect(outerConnectCallback);
  innerChannel.connect(innerConnectCallback);
  mockClock.tick(1000);

  // Check that channels were connected and callbacks invoked.
  assertEquals(1, outerConnectCallback.getCallCount());
  assertEquals(1, innerConnectCallback.getCallCount());
  assertTrue(outerChannel.isConnected());
  assertTrue(innerChannel.isConnected());
}

/** Tests that messages are successfully delivered to the inner peer. */
function testSend_outerToInner() {
  var serviceCallback = goog.testing.recordFunction();

  // Register a service handler in the inner channel.
  innerChannel.registerService('svc', function(payload) {
    assertEquals('hello', payload);
    serviceCallback();
  });

  // Connect the two channels.
  outerChannel.connect();
  innerChannel.connect();
  mockClock.tick(1000);

  // Send a message.
  outerChannel.send('svc', 'hello');
  mockClock.tick(1000);

  // Check that the message was handled.
  assertEquals(1, serviceCallback.getCallCount());
}

/** Tests that messages are successfully delivered to the outer peer. */
function testSend_innerToOuter() {
  var serviceCallback = goog.testing.recordFunction();

  // Register a service handler in the inner channel.
  outerChannel.registerService('svc', function(payload) {
    assertEquals('hello', payload);
    serviceCallback();
  });

  // Connect the two channels.
  outerChannel.connect();
  innerChannel.connect();
  mockClock.tick(1000);

  // Send a message.
  innerChannel.send('svc', 'hello');
  mockClock.tick(1000);

  // Check that the message was handled.
  assertEquals(1, serviceCallback.getCallCount());
}

/** Tests that closing the outer peer does not cause an error. */
function testSend_outerPeerClosed() {
  // Connect the inner channel.
  innerChannel.connect();
  mockClock.tick(1000);

  // Close the outer peer before it has a chance to connect.
  closeWindow(innerChannel.getPeerWindowObject());

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/** Tests that closing the inner peer does not cause an error. */
function testSend_innerPeerClosed() {
  // Connect the outer channel.
  outerChannel.connect();
  mockClock.tick(1000);

  // Close the inner peer before it has a chance to connect.
  closeWindow(outerChannel.getPeerWindowObject());

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/** Tests that partially closing the outer peer does not cause an error. */
function testSend_outerPeerClosing() {
  // Connect the inner channel.
  innerChannel.connect();
  mockClock.tick(1000);

  // Close the outer peer before it has a chance to connect, but
  // leave closed set to false to simulate a partially closed window.
  closeWindow(innerChannel.getPeerWindowObject());
  innerChannel.getPeerWindowObject().closed = false;

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/** Tests that partially closing the inner peer does not cause an error. */
function testSend_innerPeerClosing() {
  // Connect the outer channel.
  outerChannel.connect();
  mockClock.tick(1000);

  // Close the inner peer before it has a chance to connect, but
  // leave closed set to false to simulate a partially closed window.
  closeWindow(outerChannel.getPeerWindowObject());
  outerChannel.getPeerWindowObject().closed = false;

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/**
 * Creates a channel with the specified configuration, using frame polling.
 * @param {!goog.net.xpc.CrossPageChannelRole} role The channel role.
 * @param {string} channelName The channel name.
 * @param {string} fromHostName The host name of the window hosting the channel.
 * @param {!Object} fromWindow The window hosting the channel.
 * @param {string} toHostName The host name of the peer window.
 * @param {!Object} toWindow The peer window.
 */
function createChannel(
    role, channelName, fromHostName, fromWindow, toHostName, toWindow) {
  // Build a channel config using frame polling.
  var channelConfig = goog.object.create(
      goog.net.xpc.CfgFields.ROLE, role, goog.net.xpc.CfgFields.PEER_HOSTNAME,
      toHostName, goog.net.xpc.CfgFields.CHANNEL_NAME, channelName,
      goog.net.xpc.CfgFields.LOCAL_POLL_URI, fromHostName + '/robots.txt',
      goog.net.xpc.CfgFields.PEER_POLL_URI, toHostName + '/robots.txt',
      goog.net.xpc.CfgFields.TRANSPORT,
      goog.net.xpc.TransportTypes.IFRAME_POLLING);

  // Build the channel.
  var channel = new goog.net.xpc.CrossPageChannel(channelConfig);
  channel.setPeerWindowObject(toWindow);

  // Update the transport's getWindow, to return the correct host window.
  channel.createTransport_();
  channel.transport_.getWindow = goog.functions.constant(fromWindow);
  return channel;
}

/**
 * Creates a mock window to use as a peer. The peer window will host the frame
 * elements.
 * @param {string} url The peer window's initial URL.
 */
function createMockPeerWindow(url) {
  var mockPeer = createMockWindow(url);

  // Update the appendChild method to use a mock frame window.
  mockPeer.document.body.appendChild = function(el) {
    assertEquals(goog.dom.TagName.IFRAME, el.tagName);
    mockPeer.frames[el.name] = createMockWindow(el.src);
    mockPeer.document.body.element.appendChild(el);
  };

  return mockPeer;
}

/**
 * Creates a mock window.
 * @param {string} url The window's initial URL.
 */
function createMockWindow(url) {
  // Create the mock window, document and body.
  var mockWindow = {};
  var mockDocument = {};
  var mockBody = {};
  var mockLocation = {};

  // Configure the mock window's document body.
  mockBody.element = goog.dom.createDom(goog.dom.TagName.BODY);

  // Configure the mock window's document.
  mockDocument.body = mockBody;

  // Configure the mock window's location.
  mockLocation.href = url;
  mockLocation.replace = function(value) { mockLocation.href = value; };

  // Configure the mock window.
  mockWindow.document = mockDocument;
  mockWindow.frames = {};
  mockWindow.location = mockLocation;
  mockWindow.setTimeout = goog.Timer.callOnce;

  return mockWindow;
}

/**
 * Emulates closing the specified window by clearing frames, document and
 * location.
 */
function closeWindow(targetWindow) {
  // Close any child frame windows.
  for (var frameName in targetWindow.frames) {
    closeWindow(targetWindow.frames[frameName]);
  }

  // Clear the target window, set closed to true.
  targetWindow.closed = true;
  targetWindow.frames = null;
  targetWindow.document = null;
  targetWindow.location = null;
}
<commit_msg>Add a few more type annotations to improve xrefs in this file.<commit_after>// Copyright 2012 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

goog.provide('goog.net.xpc.IframePollingTransportTest');
goog.setTestOnly('goog.net.xpc.IframePollingTransportTest');

goog.require('goog.Timer');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.functions');
goog.require('goog.net.xpc.CfgFields');
goog.require('goog.net.xpc.CrossPageChannel');
goog.require('goog.net.xpc.CrossPageChannelRole');
goog.require('goog.net.xpc.TransportTypes');
goog.require('goog.object');
goog.require('goog.testing.MockClock');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.recordFunction');

/** @type {?goog.testing.MockClock} */
var mockClock = null;

/** @type {?goog.net.xpc.CrossPageChannel} */
var outerChannel = null;

/** @type {?goog.net.xpc.CrossPageChannel} */
var innerChannel = null;

function setUp() {
  mockClock = new goog.testing.MockClock(true /* opt_autoInstall */);

  // Create the peer windows.
  var outerPeerHostName = 'https://www.youtube.com';
  var outerPeerWindow = createMockPeerWindow(outerPeerHostName);

  var innerPeerHostName = 'https://www.google.com';
  var innerPeerWindow = createMockPeerWindow(innerPeerHostName);

  // Create the channels.
  outerChannel = createChannel(
      goog.net.xpc.CrossPageChannelRole.OUTER, 'test', outerPeerHostName,
      outerPeerWindow, innerPeerHostName, innerPeerWindow);
  innerChannel = createChannel(
      goog.net.xpc.CrossPageChannelRole.INNER, 'test', innerPeerHostName,
      innerPeerWindow, outerPeerHostName, outerPeerWindow);
}

function tearDown() {
  outerChannel.dispose();
  innerChannel.dispose();
  mockClock.uninstall();
}

/** Tests that connection happens normally and callbacks are invoked. */
function testConnect() {
  var outerConnectCallback = goog.testing.recordFunction();
  var innerConnectCallback = goog.testing.recordFunction();

  // Connect the two channels.
  outerChannel.connect(outerConnectCallback);
  innerChannel.connect(innerConnectCallback);
  mockClock.tick(1000);

  // Check that channels were connected and callbacks invoked.
  assertEquals(1, outerConnectCallback.getCallCount());
  assertEquals(1, innerConnectCallback.getCallCount());
  assertTrue(outerChannel.isConnected());
  assertTrue(innerChannel.isConnected());
}

/** Tests that messages are successfully delivered to the inner peer. */
function testSend_outerToInner() {
  var serviceCallback = goog.testing.recordFunction();

  // Register a service handler in the inner channel.
  innerChannel.registerService('svc', function(payload) {
    assertEquals('hello', payload);
    serviceCallback();
  });

  // Connect the two channels.
  outerChannel.connect();
  innerChannel.connect();
  mockClock.tick(1000);

  // Send a message.
  outerChannel.send('svc', 'hello');
  mockClock.tick(1000);

  // Check that the message was handled.
  assertEquals(1, serviceCallback.getCallCount());
}

/** Tests that messages are successfully delivered to the outer peer. */
function testSend_innerToOuter() {
  var serviceCallback = goog.testing.recordFunction();

  // Register a service handler in the inner channel.
  outerChannel.registerService('svc', function(payload) {
    assertEquals('hello', payload);
    serviceCallback();
  });

  // Connect the two channels.
  outerChannel.connect();
  innerChannel.connect();
  mockClock.tick(1000);

  // Send a message.
  innerChannel.send('svc', 'hello');
  mockClock.tick(1000);

  // Check that the message was handled.
  assertEquals(1, serviceCallback.getCallCount());
}

/** Tests that closing the outer peer does not cause an error. */
function testSend_outerPeerClosed() {
  // Connect the inner channel.
  innerChannel.connect();
  mockClock.tick(1000);

  // Close the outer peer before it has a chance to connect.
  closeWindow(innerChannel.getPeerWindowObject());

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/** Tests that closing the inner peer does not cause an error. */
function testSend_innerPeerClosed() {
  // Connect the outer channel.
  outerChannel.connect();
  mockClock.tick(1000);

  // Close the inner peer before it has a chance to connect.
  closeWindow(outerChannel.getPeerWindowObject());

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/** Tests that partially closing the outer peer does not cause an error. */
function testSend_outerPeerClosing() {
  // Connect the inner channel.
  innerChannel.connect();
  mockClock.tick(1000);

  // Close the outer peer before it has a chance to connect, but
  // leave closed set to false to simulate a partially closed window.
  closeWindow(innerChannel.getPeerWindowObject());
  innerChannel.getPeerWindowObject().closed = false;

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/** Tests that partially closing the inner peer does not cause an error. */
function testSend_innerPeerClosing() {
  // Connect the outer channel.
  outerChannel.connect();
  mockClock.tick(1000);

  // Close the inner peer before it has a chance to connect, but
  // leave closed set to false to simulate a partially closed window.
  closeWindow(outerChannel.getPeerWindowObject());
  outerChannel.getPeerWindowObject().closed = false;

  // Allow timers to execute (and fail).
  mockClock.tick(1000);
}

/**
 * Creates a channel with the specified configuration, using frame polling.
 * @param {!goog.net.xpc.CrossPageChannelRole} role The channel role.
 * @param {string} channelName The channel name.
 * @param {string} fromHostName The host name of the window hosting the channel.
 * @param {!Object} fromWindow The window hosting the channel.
 * @param {string} toHostName The host name of the peer window.
 * @param {!Object} toWindow The peer window.
 * @return {!goog.net.xpc.CrossPageChannel}
 */
function createChannel(
    role, channelName, fromHostName, fromWindow, toHostName, toWindow) {
  // Build a channel config using frame polling.
  var channelConfig = goog.object.create(
      goog.net.xpc.CfgFields.ROLE, role, goog.net.xpc.CfgFields.PEER_HOSTNAME,
      toHostName, goog.net.xpc.CfgFields.CHANNEL_NAME, channelName,
      goog.net.xpc.CfgFields.LOCAL_POLL_URI, fromHostName + '/robots.txt',
      goog.net.xpc.CfgFields.PEER_POLL_URI, toHostName + '/robots.txt',
      goog.net.xpc.CfgFields.TRANSPORT,
      goog.net.xpc.TransportTypes.IFRAME_POLLING);

  // Build the channel.
  var channel = new goog.net.xpc.CrossPageChannel(channelConfig);
  channel.setPeerWindowObject(toWindow);

  // Update the transport's getWindow, to return the correct host window.
  channel.createTransport_();
  channel.transport_.getWindow = goog.functions.constant(fromWindow);
  return channel;
}

/**
 * Creates a mock window to use as a peer. The peer window will host the frame
 * elements.
 * @param {string} url The peer window's initial URL.
 */
function createMockPeerWindow(url) {
  var mockPeer = createMockWindow(url);

  // Update the appendChild method to use a mock frame window.
  mockPeer.document.body.appendChild = function(el) {
    assertEquals(goog.dom.TagName.IFRAME, el.tagName);
    mockPeer.frames[el.name] = createMockWindow(el.src);
    mockPeer.document.body.element.appendChild(el);
  };

  return mockPeer;
}

/**
 * Creates a mock window.
 * @param {string} url The window's initial URL.
 */
function createMockWindow(url) {
  // Create the mock window, document and body.
  var mockWindow = {};
  var mockDocument = {};
  var mockBody = {};
  var mockLocation = {};

  // Configure the mock window's document body.
  mockBody.element = goog.dom.createDom(goog.dom.TagName.BODY);

  // Configure the mock window's document.
  mockDocument.body = mockBody;

  // Configure the mock window's location.
  mockLocation.href = url;
  mockLocation.replace = function(value) { mockLocation.href = value; };

  // Configure the mock window.
  mockWindow.document = mockDocument;
  mockWindow.frames = {};
  mockWindow.location = mockLocation;
  mockWindow.setTimeout = goog.Timer.callOnce;

  return mockWindow;
}

/**
 * Emulates closing the specified window by clearing frames, document and
 * location.
 */
function closeWindow(targetWindow) {
  // Close any child frame windows.
  for (var frameName in targetWindow.frames) {
    closeWindow(targetWindow.frames[frameName]);
  }

  // Clear the target window, set closed to true.
  targetWindow.closed = true;
  targetWindow.frames = null;
  targetWindow.document = null;
  targetWindow.location = null;
}
<|endoftext|>


<commit_before>var EXAMPLE_MAX_HEIGHT = 98,
    DEFAULT_SHOW_PARAMS = 5;

$(document).ready(function() {
    // 移动端导航
    var $openPanel = $('.open-panel');
    var $contentLeft = $('.content-left');
    var $contentLeftWidth = $contentLeft.width() - 1;
    var $ydoc = $('.ydoc');
    var $mask = $('.mask');
    var $versionSelector = $('.version-selector');
    var $versionMask = $('.m-version-mask');
    var isPanelHide = true;
    var winWidth = $(window).width();
    var h2 = $('.content-right').find('h2');
    var h3 = $('.content-right').find('h3');
    var a = $('.content-left').find('a');
    var lis = $contentLeft.find('li');
    var titles = [];
    var menus = [];
    $ydoc.addClass('hidden');
    if (isWechat() && $contentLeft[0]) {
        $ydoc.addClass('off-webkit-scroll');
    }
    for (var i = 0; i < a.length; i++) {
        menus.push({
            name: $(a[i]).attr('href').split('#')[1],
            offsetTop: $(a[i]).offset().top - 77,
            parent: $(a[i]).parent()
        })
    }
    for (var i = 0; i < h2.length; i++) {
        titles.push({
            name: h2[i].id,
            jq: $(h2[i]),
            offsetTop: $(h2[i]).offset().top
        })
    }
    for (var i = 0; i < h3.length; i++) {
        titles.push({
            name: h3[i].id,
            jq: $(h3[i]),
            offsetTop: $(h3[i]).offset().top
        })
    }
    titles.sort(sortAsOffset('offsetTop'));

    $openPanel.on('click', function() {
        if (isPanelHide) { // 点击弹出panel
            isPanelHide = false;
            $ydoc.addClass('hidden');
            $mask.show();
            setTimeout(function() {
                $mask.addClass('show');
            }, 50)
            $openPanel.css({
                'transform': 'translateX(-' + $contentLeftWidth + 'px)'
            })
            $contentLeft.css({
                'transform': 'translateX(-' + $contentLeftWidth + 'px)'
            })
        } else { // 点击隐藏panel
            isPanelHide = true;
            $ydoc.removeClass('hidden');
            $mask.removeClass('show');
            setTimeout(function() {
                $mask.hide();
            }, 400)
            $openPanel.css({
                'transform': 'translateX(0px)'
            })
            $contentLeft.css({
                'transform': 'translateX(0px)'
            })
        }
        var scrollTop = $ydoc.scrollTop();
        // 遍历主页面的标题，找到当前窗口顶部的标题
        for (var i = 0; i < titles.length; i++) {
            if (titles[i].offsetTop > scrollTop) {
                // 遍历侧栏，找到对应的标题
                for (var j in menus) {
                    if (menus[j].name == titles[i].name) {
                        lis.removeClass('active');
                        menus[j].parent.addClass('active');
                        $('.docs-sidenav').scrollTop(menus[j].offsetTop);
                        return;
                    }
                }
                return;
            }
        }
    });

    $ydoc.removeClass('hidden');
    $ydoc.on('scroll', function() {
        sessionStorage.setItem('offsetTop', $ydoc.scrollTop());
    })
    // 待元素获获取offsetTop值之后再设置ydoc的offsetTop
    if (sessionStorage.offsetTop) {
        $ydoc.scrollTop(sessionStorage.offsetTop);
    }
    // $openPanel.trigger('click');
    $mask.on('click', function() {
        if (!isPanelHide) {
            $openPanel.click();
        }
    });

    // PC端导航
    $('.navbar-toggle').click(function() {
        $(this).next(".ydoc-nav").toggle();
    });

    $('.docs-sidenav li').click(function(e) {
        $('.docs-sidenav li').removeClass('active');
        $(this).addClass('active');
        if (!isPanelHide) {
            $openPanel.trigger('click');
        }
    });
    $ydoc.click(function(e) {
        if ($(e.target).data('target') !== 'version') {
            $versionMask.hide();
        }
    })
    $versionSelector.click(function(e) {
        $versionMask.show();
        console.log('e');
    });

    $('.markdown-body pre').map(function(i, item) {
        $(item).addClass('ydoc-example').append('
copy

已复制
');
        $(item).children('code').addClass('js-code-'+i);
    });

    var winHeight = $(window).height() - 44,
        sidebar = $('.docs-sidebar');
    var docSideNav = $('.docs-sidenav');
    if (winWidth > 767) {
        docSideNav.width($contentLeftWidth);
    }
    if (sidebar.height() > winHeight) {
        sidebar.css('max-height', winHeight + 'px');
        $('.docs-sidenav').css('max-height', winHeight + 'px');
        if (winWidth < 768) {
            $('.docs-sidenav').css({
                'overflow-x': 'hidden'
            });
        }
        var activeMenu,
            barScroll = false;

        sidebar.on('mouseover', function() {
            barScroll = true;
        });
        sidebar.on('mouseout', function() {
            barScroll = false;
        });
    };

    $(window).on('scroll', function(e) {
        if ($(this).scrollTop() > ($('.footer').offset().top - $(window).height())) {
            winHeight = $(window).height() - $('.footer').outerHeight() - 44;
            sidebar.css('max-height', winHeight + 'px');
            $('.docs-sidenav').css('max-height', winHeight + 'px');
        } else {
            winHeight = $(window).height() - 44;
            sidebar.css('max-height', winHeight + 'px');
            $('.docs-sidenav').css('max-height', winHeight + 'px');
        }

        if (!barScroll) {
            var activeItem = $('.docs-sidebar li.active a');
            if (activeItem.length) {
                if (!activeMenu || (activeMenu.attr('href') != activeItem.attr('href'))) {
                    activeMenu = activeItem;
                    var top = activeMenu.offset().top - sidebar.offset().top;
                    if (top < 0) {
                        //sidebar.scrollTop(sidebar.scrollTop() + top);
                        $('.docs-sidenav').scrollTop($('.docs-sidenav').scrollTop() + top);
                    } else if (top > winHeight - 88) {
                        //sidebar.scrollTop(sidebar.scrollTop() + top - winHeight + 44);
                        $('.docs-sidenav').scrollTop($('.docs-sidenav').scrollTop() + top - winHeight + 88);
                    }
                }
            }
        }
    });

    // 退出全屏浏览器窗口大小改变，不触发resize
    $(window).on('resize', function(e) {
        $contentLeftWidth = $contentLeft.width() - 1;
    });

    function sortAsOffset(propertyName) {
        return function(obj1, obj2) {
            var val1 = obj1[propertyName];
            var val2 = obj2[propertyName];
            if (val1 < val2) {
                return -1;
            } else if (val1 > val2) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    function isWechat() {
        var ua = navigator.userAgent.toLowerCase();
        if (ua.match(/MicroMessenger/i) == "micromessenger") {
            return true;
        } else {
            return false;
        }
    }

    // 代码复制功能
    var clipboard = new Clipboard('.js-copy');

    clipboard.on('success', function(e) {
      var copyNumber = $(e.trigger).attr('data-copy-number');
      $('.copy-tip-'+copyNumber).show();
      setTimeout(function() {
          $('.copy-tip-'+copyNumber).hide();
      }, 1000);
      e.clearSelection();
    });

});
<commit_msg>docs: 更新文档<commit_after>var EXAMPLE_MAX_HEIGHT = 98,
    DEFAULT_SHOW_PARAMS = 5;

$(document).ready(function() {
    // 移动端导航
    var $openPanel = $('.open-panel');
    var $contentLeft = $('.content-left');
    var $contentLeftWidth = $contentLeft.width() - 1;
    var $ydoc = $('.ydoc');
    var $mask = $('.mask');
    var $versionSelector = $('.version-selector');
    var $versionMask = $('.m-version-mask');
    var isPanelHide = true;
    var winWidth = $(window).width();
    var h2 = $('.content-right').find('h2');
    var h3 = $('.content-right').find('h3');
    var a = $('.content-left').find('a');
    var lis = $contentLeft.find('li');
    var titles = [];
    var menus = [];
    $ydoc.addClass('hidden');
    if (isWechat() && $contentLeft[0]) {
        $ydoc.addClass('off-webkit-scroll');
    }
    for (var i = 0; i < a.length; i++) {
        menus.push({
            name: $(a[i]).attr('href').split('#')[1],
            offsetTop: $(a[i]).offset().top - 77,
            parent: $(a[i]).parent()
        })
    }
    for (var i = 0; i < h2.length; i++) {
        titles.push({
            name: h2[i].id,
            jq: $(h2[i]),
            offsetTop: $(h2[i]).offset().top
        })
    }
    for (var i = 0; i < h3.length; i++) {
        titles.push({
            name: h3[i].id,
            jq: $(h3[i]),
            offsetTop: $(h3[i]).offset().top
        })
    }
    titles.sort(sortAsOffset('offsetTop'));

    $openPanel.on('click', function() {
        if (isPanelHide) { // 点击弹出panel
            isPanelHide = false;
            $ydoc.addClass('hidden');
            $mask.show();
            setTimeout(function() {
                $mask.addClass('show');
            }, 50)
            $openPanel.css({
                'transform': 'translateX(-' + $contentLeftWidth + 'px)'
            })
            $contentLeft.css({
                'transform': 'translateX(-' + $contentLeftWidth + 'px)'
            })
        } else { // 点击隐藏panel
            isPanelHide = true;
            $ydoc.removeClass('hidden');
            $mask.removeClass('show');
            setTimeout(function() {
                $mask.hide();
            }, 400)
            $openPanel.css({
                'transform': 'translateX(0px)'
            })
            $contentLeft.css({
                'transform': 'translateX(0px)'
            })
        }
        var scrollTop = $ydoc.scrollTop();
        // 遍历主页面的标题，找到当前窗口顶部的标题
        for (var i = 0; i < titles.length; i++) {
            if (titles[i].offsetTop > scrollTop) {
                // 遍历侧栏，找到对应的标题
                for (var j in menus) {
                    if (menus[j].name == titles[i].name) {
                        lis.removeClass('active');
                        menus[j].parent.addClass('active');
                        $('.docs-sidenav').scrollTop(menus[j].offsetTop);
                        return;
                    }
                }
                return;
            }
        }
    });

    $ydoc.removeClass('hidden');
    $ydoc.on('scroll', function() {
        sessionStorage.setItem('offsetTop', $ydoc.scrollTop());
    })
    // 待元素获获取offsetTop值之后再设置ydoc的offsetTop
    if (sessionStorage.offsetTop) {
        $ydoc.scrollTop(sessionStorage.offsetTop);
    }
    // $openPanel.trigger('click');
    $mask.on('click', function() {
        if (!isPanelHide) {
            $openPanel.click();
        }
    });

    // PC端导航
    $('.navbar-toggle').click(function() {
        $(this).next(".ydoc-nav").toggle();
    });

    $('.docs-sidenav li').click(function(e) {
        $('.docs-sidenav li').removeClass('active');
        $(this).addClass('active');
        if (!isPanelHide) {
            $openPanel.trigger('click');
        }
    });
    $ydoc.click(function(e) {
        if ($(e.target).data('target') !== 'version') {
            $versionMask.hide();
        }
    })
    $versionSelector.click(function(e) {
        $versionMask.show();
        console.log('e');
    });

    $('.markdown-body pre').map(function(i, item) {
        $(item).addClass('ydoc-example').append('
copy

已复制
');
        $(item).children('code').addClass('js-code js-code-'+i);
    });

    var winHeight = $(window).height() - 44,
        sidebar = $('.docs-sidebar');
    var docSideNav = $('.docs-sidenav');
    if (winWidth > 767) {
        docSideNav.width($contentLeftWidth);
    }
    if (sidebar.height() > winHeight) {
        sidebar.css('max-height', winHeight + 'px');
        $('.docs-sidenav').css('max-height', winHeight + 'px');
        if (winWidth < 768) {
            $('.docs-sidenav').css({
                'overflow-x': 'hidden'
            });
        }
        var activeMenu,
            barScroll = false;

        sidebar.on('mouseover', function() {
            barScroll = true;
        });
        sidebar.on('mouseout', function() {
            barScroll = false;
        });
    };

    $(window).on('scroll', function(e) {
        if ($(this).scrollTop() > ($('.footer').offset().top - $(window).height())) {
            winHeight = $(window).height() - $('.footer').outerHeight() - 44;
            sidebar.css('max-height', winHeight + 'px');
            $('.docs-sidenav').css('max-height', winHeight + 'px');
        } else {
            winHeight = $(window).height() - 44;
            sidebar.css('max-height', winHeight + 'px');
            $('.docs-sidenav').css('max-height', winHeight + 'px');
        }

        if (!barScroll) {
            var activeItem = $('.docs-sidebar li.active a');
            if (activeItem.length) {
                if (!activeMenu || (activeMenu.attr('href') != activeItem.attr('href'))) {
                    activeMenu = activeItem;
                    var top = activeMenu.offset().top - sidebar.offset().top;
                    if (top < 0) {
                        //sidebar.scrollTop(sidebar.scrollTop() + top);
                        $('.docs-sidenav').scrollTop($('.docs-sidenav').scrollTop() + top);
                    } else if (top > winHeight - 88) {
                        //sidebar.scrollTop(sidebar.scrollTop() + top - winHeight + 44);
                        $('.docs-sidenav').scrollTop($('.docs-sidenav').scrollTop() + top - winHeight + 88);
                    }
                }
            }
        }
    });

    // 退出全屏浏览器窗口大小改变，不触发resize
    $(window).on('resize', function(e) {
        $contentLeftWidth = $contentLeft.width() - 1;
    });

    function sortAsOffset(propertyName) {
        return function(obj1, obj2) {
            var val1 = obj1[propertyName];
            var val2 = obj2[propertyName];
            if (val1 < val2) {
                return -1;
            } else if (val1 > val2) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    function isWechat() {
        var ua = navigator.userAgent.toLowerCase();
        if (ua.match(/MicroMessenger/i) == "micromessenger") {
            return true;
        } else {
            return false;
        }
    }

    // 代码复制功能
    var clipboard = new Clipboard('.js-copy');

    clipboard.on('success', function(e) {
      var copyNumber = $(e.trigger).attr('data-copy-number');
      $('.copy-tip-'+copyNumber).show();
      setTimeout(function() {
          $('.copy-tip-'+copyNumber).hide();
      }, 1000);
      e.clearSelection();
    });

});
<|endoftext|>


<commit_before>'use strict';

describe('The translate loader service test suite', function () {
    var $loaderService, $storageService, $events, $httpBackend, options;

    beforeEach(function () {
        module('mutant-ng-translate');

        inject(function ($translateLoaderSvc, $translateStorageSvc, $translateEvents, _$httpBackend_) {
            $loaderService = $translateLoaderSvc;
            $storageService = $translateStorageSvc;
            $events = $translateEvents;
            $httpBackend = _$httpBackend_;
        });

        options = {
            defaultLang: 'en',
            urlTemplate: '/locale-{part}-{lang}.json',
            cache: {
                translations: true,
                lang: true
            },
            dataTransformation: function (x) {
                return x;
            },
            preload: {
                enabled: true,
                langs: [],
                delay: 0
            }
        };

        $storageService.config(options);
        $loaderService.config(options, $storageService.setTranslations);
    });

    describe('>> Common tests', function () {
        it('should be defined', function () {
            expect($loaderService).toBeDefined();
        });

        it('should be an object', function () {
            expect(typeof $loaderService).toBe('object');
        });
    });

    describe('>> Config tests', function () {
        it('should save options and storage callback', function() {
            expect($loaderService.options).toEqual(options);
            expect($loaderService.storageCallback).toEqual($storageService.setTranslations);
        });

        it('should sync options', function () {
            options.preload.delay = 2000;

            expect($loaderService.options.preload.delay).toEqual(2000);
        });
    });

    describe('>> Syncronization tests', function () {
        describe('>> Loading', function() {
            it('should return undefined if part for lang not start loading yet', function () {
                var status = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                expect(status).toBeUndefined();
            });

            it('should corretly return loading status', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status1 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status2 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status3 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status4 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                expect(status1).toBe(true);
                expect(status2).toBe(false);
                expect(status3).toBe(true);
                expect(status4).toBe(false);
            });

            it('should return false if part for lang not loaded yet', function () {
                var status1 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status2 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                expect(status1).toBe(false);
                expect(status2).toBe(false);
            });

            it('should corretly return loaded status', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status1 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status2 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                expect(status1).toBe(true);
                expect(status2).toBe(true);
            });

            it('should return true if part for lang not loading and not loaded', function() {
                var status = $loaderService.sync.needLoad({ name: 'first' }, 'en');

                expect(status).toBe(true);
            });

            it('should return false if part for lang loading', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status = $loaderService.sync.needLoad({ name: 'first' }, 'en');

                expect(status).toBe(false);
            });

            it('should return false if part for lang loaded', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status = $loaderService.sync.needLoad({ name: 'first' }, 'en');

                expect(status).toBe(false);
            });
        });

        describe('>> Counter', function() {
            it('should set counter for lang to two', function() {
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.increaseCounter('en');

                expect($loaderService.sync.counter['en']).toBe(2);
            });

            it('should set counter for lang to zero', function() {
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.resetCounter('en');

                expect($loaderService.sync.counter['en']).toBe(0);
            });

            it('should generate all parts loaded event if counter for lang equal to parts count', function () {
                var callback = jasmine.createSpy('callback');

                $events.allPartsLoaded.subscribe(callback);

                $loaderService.addPart('first', 'en');
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.checkCounter('en');

                expect(callback.calls.count()).toBe(1);
                expect(callback.calls.argsFor(0)).toEqual([{lang: 'en'}]);
            });
        });
    });

    describe('>> Parts tests', function () {
        afterEach(function () {
            $httpBackend.verifyNoOutstandingExpectation();
            $httpBackend.verifyNoOutstandingRequest();
        });

        describe('>> Add', function () {
            it('should add new part and load it', function () {
                $loaderService.addPart('first', 'en');

                expect($loaderService.parts).toEqual([{ name: 'first' }]);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
            });

            it('should not add two parts and load them', function () {
                $loaderService.addParts(['first', 'second'], 'en');

                expect($loaderService.parts).toEqual([{ name: 'first' }, { name: 'second' }]);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });

            xit('should not add part with already dublicate name', function () {
                $loaderService.addPart('first', 'en');
                $loaderService.addPart('first', 'en');

                expect($loaderService.parts).toEqual([{ name: 'first' }]);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
            });
        });

        describe('>> Load', function () {
            it('should load part for lang and put it to storage', function() {
                $loaderService.loadPart({ name: 'first' }, 'en');

                $httpBackend
                    .expect('GET', '/locale-first-en.json')
                    .respond({ test: 'test' });
                $httpBackend.flush();

                var translations = $storageService.getTranslations('en');

                expect(translations).toEqual({ test: 'test' });
            });

            it('should switch loading status correctly', function () {
                var part = { name: 'first' };

                $loaderService.loadPart(part, 'en');
                var status1 = $loaderService.sync.isLoading(part, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
                var status2 = $loaderService.sync.isLoading(part, 'en');

                expect(status1).toBe(true);
                expect(status2).toBe(false);
            });

            it('should switch loaded status correctly', function () {
                var part = { name: 'first' };

                $loaderService.loadPart(part, 'en');
                var status1 = $loaderService.sync.isLoaded(part, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
                var status2 = $loaderService.sync.isLoaded(part, 'en');

                $loaderService.loadPart(part, 'en');
                var status3 = $loaderService.sync.isLoaded(part, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                expect(status1).toBe(false);
                expect(status2).toBe(true);
                expect(status3).toBe(true);
            });

            it('should increase counter by one for one part loaded', function() {
                $loaderService.loadPart({ name: 'first' }, 'en');
                $loaderService.loadPart({ name: 'second' }, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();

                expect($loaderService.sync.counter['en']).toBe(2);
            });

            it('should generate part loaded event', function () {
                var callback = jasmine.createSpy('callback');

                $events.partLoaded.subscribe(callback);

                $loaderService.loadPart({ name: 'first' }, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                expect(callback.calls.count()).toBe(1);
                expect(callback.calls.argsFor(0)).toEqual([{ part: 'first', lang: 'en' }]);
            });

            it('should load all parts', function() {
                $loaderService.parts.push({ name: 'first' });
                $loaderService.parts.push({ name: 'second' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });

            it('should load only parts not loaded early', function () {
                $loaderService.parts.push({ name: 'first' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                $loaderService.parts.push({ name: 'second' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });

            it('should load all parts if called with force', function() {
                $loaderService.parts.push({ name: 'first' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                $loaderService.parts.push({ name: 'second' });

                $loaderService.loadParts('en', true);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });
        });
    });
});<commit_msg>implement preload tests for translate loader service suite<commit_after>'use strict';

describe('The translate loader service test suite', function () {
    var $loaderService, $storageService, $events, $httpBackend, $timeout, options;

    beforeEach(function () {
        module('mutant-ng-translate');

        inject(function ($translateLoaderSvc, $translateStorageSvc, $translateEvents, _$httpBackend_, _$timeout_) {
            $loaderService = $translateLoaderSvc;
            $storageService = $translateStorageSvc;
            $events = $translateEvents;
            $httpBackend = _$httpBackend_;
            $timeout = _$timeout_;
        });

        options = {
            defaultLang: 'en',
            urlTemplate: '/locale-{part}-{lang}.json',
            cache: {
                translations: true,
                lang: true
            },
            dataTransformation: function (x) {
                return x;
            },
            preload: {
                enabled: true,
                langs: ['en', 'ru'],
                delay: 0
            }
        };

        $storageService.config(options);
        $loaderService.config(options, $storageService.setTranslations);
    });

    describe('>> Common tests', function () {
        it('should be defined', function () {
            expect($loaderService).toBeDefined();
        });

        it('should be an object', function () {
            expect(typeof $loaderService).toBe('object');
        });
    });

    describe('>> Config tests', function () {
        it('should save options and storage callback', function() {
            expect($loaderService.options).toEqual(options);
            expect($loaderService.storageCallback).toEqual($storageService.setTranslations);
        });

        it('should sync options', function () {
            options.preload.delay = 2000;

            expect($loaderService.options.preload.delay).toEqual(2000);
        });
    });

    describe('>> Syncronization tests', function () {
        describe('>> Loading', function() {
            it('should return undefined if part for lang not start loading yet', function () {
                var status = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                expect(status).toBeUndefined();
            });

            it('should corretly return loading status', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status1 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status2 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status3 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status4 = $loaderService.sync.isLoading({ name: 'first' }, 'en');

                expect(status1).toBe(true);
                expect(status2).toBe(false);
                expect(status3).toBe(true);
                expect(status4).toBe(false);
            });

            it('should return false if part for lang not loaded yet', function () {
                var status1 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status2 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                expect(status1).toBe(false);
                expect(status2).toBe(false);
            });

            it('should corretly return loaded status', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status1 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status2 = $loaderService.sync.isLoaded({ name: 'first' }, 'en');

                expect(status1).toBe(true);
                expect(status2).toBe(true);
            });

            it('should return true if part for lang not loading and not loaded', function() {
                var status = $loaderService.sync.needLoad({ name: 'first' }, 'en');

                expect(status).toBe(true);
            });

            it('should return false if part for lang loading', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                var status = $loaderService.sync.needLoad({ name: 'first' }, 'en');

                expect(status).toBe(false);
            });

            it('should return false if part for lang loaded', function () {
                $loaderService.sync.loadingOn({ name: 'first' }, 'en');
                $loaderService.sync.loadingOff({ name: 'first' }, 'en');
                var status = $loaderService.sync.needLoad({ name: 'first' }, 'en');

                expect(status).toBe(false);
            });
        });

        describe('>> Counter', function() {
            it('should set counter for lang to two', function() {
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.increaseCounter('en');

                expect($loaderService.sync.counter['en']).toBe(2);
            });

            it('should set counter for lang to zero', function() {
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.resetCounter('en');

                expect($loaderService.sync.counter['en']).toBe(0);
            });

            it('should generate all parts loaded event if counter for lang equal to parts count', function () {
                var callback = jasmine.createSpy('callback');

                $events.allPartsLoaded.subscribe(callback);

                $loaderService.addPart('first', 'en');
                $loaderService.sync.increaseCounter('en');
                $loaderService.sync.checkCounter('en');

                expect(callback.calls.count()).toBe(1);
                expect(callback.calls.argsFor(0)).toEqual([{lang: 'en'}]);
            });
        });
    });

    describe('>> Parts tests', function () {
        afterEach(function () {
            $httpBackend.verifyNoOutstandingExpectation();
            $httpBackend.verifyNoOutstandingRequest();
        });

        describe('>> Add', function () {
            it('should add new part and load it', function () {
                $loaderService.addPart('first', 'en');

                expect($loaderService.parts).toEqual([{ name: 'first' }]);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
            });

            it('should not add two parts and load them', function () {
                $loaderService.addParts(['first', 'second'], 'en');

                expect($loaderService.parts).toEqual([{ name: 'first' }, { name: 'second' }]);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });

            xit('should not add part with already dublicate name', function () {
                $loaderService.addPart('first', 'en');
                $loaderService.addPart('first', 'en');

                expect($loaderService.parts).toEqual([{ name: 'first' }]);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
            });
        });

        describe('>> Load', function () {
            it('should load part for lang and put it to storage', function() {
                $loaderService.loadPart({ name: 'first' }, 'en');

                $httpBackend
                    .expect('GET', '/locale-first-en.json')
                    .respond({ test: 'test' });
                $httpBackend.flush();

                var translations = $storageService.getTranslations('en');

                expect(translations).toEqual({ test: 'test' });
            });

            it('should switch loading status correctly', function () {
                var part = { name: 'first' };

                $loaderService.loadPart(part, 'en');
                var status1 = $loaderService.sync.isLoading(part, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
                var status2 = $loaderService.sync.isLoading(part, 'en');

                expect(status1).toBe(true);
                expect(status2).toBe(false);
            });

            it('should switch loaded status correctly', function () {
                var part = { name: 'first' };

                $loaderService.loadPart(part, 'en');
                var status1 = $loaderService.sync.isLoaded(part, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();
                var status2 = $loaderService.sync.isLoaded(part, 'en');

                $loaderService.loadPart(part, 'en');
                var status3 = $loaderService.sync.isLoaded(part, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                expect(status1).toBe(false);
                expect(status2).toBe(true);
                expect(status3).toBe(true);
            });

            it('should increase counter by one for one part loaded', function() {
                $loaderService.loadPart({ name: 'first' }, 'en');
                $loaderService.loadPart({ name: 'second' }, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();

                expect($loaderService.sync.counter['en']).toBe(2);
            });

            it('should generate part loaded event', function () {
                var callback = jasmine.createSpy('callback');

                $events.partLoaded.subscribe(callback);

                $loaderService.loadPart({ name: 'first' }, 'en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                expect(callback.calls.count()).toBe(1);
                expect(callback.calls.argsFor(0)).toEqual([{ part: 'first', lang: 'en' }]);
            });

            it('should load all parts', function() {
                $loaderService.parts.push({ name: 'first' });
                $loaderService.parts.push({ name: 'second' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });

            it('should load only parts not loaded early', function () {
                $loaderService.parts.push({ name: 'first' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                $loaderService.parts.push({ name: 'second' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });

            it('should load all parts if called with force', function() {
                $loaderService.parts.push({ name: 'first' });

                $loaderService.loadParts('en');

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.flush();

                $loaderService.parts.push({ name: 'second' });

                $loaderService.loadParts('en', true);

                $httpBackend.expect('GET', '/locale-first-en.json').respond({});
                $httpBackend.expect('GET', '/locale-second-en.json').respond({});
                $httpBackend.flush();
            });
        });
    });

    describe('>> Preload tests', function () {
        afterEach(function () {
            $httpBackend.verifyNoOutstandingExpectation();
            $httpBackend.verifyNoOutstandingRequest();
            $timeout.verifyNoPendingTasks();
        });

        it('should start preload', function () {
            $loaderService.options.preload.enabled = true;
            $loaderService.parts.push({ name: 'first' });

            $events.allPartsLoaded.publish();

            $httpBackend.expect('GET', '/locale-first-en.json').respond({});
            $httpBackend.expect('GET', '/locale-first-ru.json').respond({});

            $timeout.flush();
            $httpBackend.flush();
            $timeout.flush();
        });

        it('should not start preload', function () {
            $loaderService.options.preload.enabled = false;
            $loaderService.parts.push({ name: 'first' });

            $events.allPartsLoaded.publish();
        });
    });
});<|endoftext|>


<commit_before>/*!
 * superbly tagfield v0.1
 * http://www.superbly.ch
 *
 * Copyright 2011, Manuel Spierenburg
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://www.superbly.ch/licenses/mit-license.txt
 * http://www.superbly.ch/licenses/gpl-2.0.txt
 *
 * Date: Sun Apr 14 00:47:29 2011 -0500
 */
(function($){
    $.fn.superblyTagField = function(userOptions) {
        var settings = {
            allowNewTags:true,
            showTagsNumber:10,
            preset:[],
            tags:[],
            complete:function() { return []; }
        };

        if(userOptions) {
            $.extend(settings, userOptions);
        }

        superblyTagField(this, settings);

        return this;
    };

    var keyMap = {
        downArrow:40,
        upArrow:38,
        enter:13,
        space:32,
        tab:9,
        backspace:8
    }

    function superblyTagField(tagField, settings) {

        var tags = settings.tags.sort();
        var preset = settings.preset;
        var allowNewTags = settings.allowNewTags;
        var showTagsNumber = settings.showTagsNumber;

        var tagstmp = tags.slice();

        // prepare needed vars
        var inserted = new Array();
        var selectedIndex = null;
        var currentValue = null;
        var currentItem = null;
        var hoverSuggestItems = false;

        tagField.css('display', 'none');

        var superblyMarkup = '

<input class="superblyTagInput" type="text" autocomplete="false">

';
        tagField.after(superblyMarkup);

        var tagInput = $(".superblyTagInput", tagField.next());
        var suggestList = tagInput.next();
        var inputItem = tagInput.parent();
        var tagList = inputItem.parent();

        // set presets
        for(i in preset){
            console.log('preset');
            addItem(preset[i]);
        }

        tagField.change(function() {
            var existingTags = tagField.val().split(/ /);
            for(var t in existingTags) {
                addItem(existingTags[t]);
            }
        });

        // events
        suggestList.mouseover(function(e){
            hoverSuggestItems = true;
        });

        suggestList.mouseleave(function(e){
            hoverSuggestItems = false;
        });

        tagInput.keyup(function(e){
            suggest($(this).val());
        });

        tagInput.focusout(function(e){
            console.log('hoverSuggestItems');
            console.log(hoverSuggestItems);
            if(!hoverSuggestItems){
                suggestList.css('display', 'none');
            }
            if(allowNewTags){
                var value = tagInput.val();
                if(value != null && value != ''){
                    console.log('focusout');
                    addItem(value, false);
                }
            }
        });

        tagInput.focus(function(e){
            currentValue = null;
        });

        tagInput.keydown(function(e){
            if(e.keyCode == keyMap.downArrow) {
                selectDown();
            }else if(e.keyCode == keyMap.upArrow) {
                selectUp()
            }else if(e.keyCode == keyMap.enter || e.keyCode == keyMap.tab || e.keyCode == keyMap.space) {
                if(currentItem != null){
                    console.log('in if');
                    addItem(currentItem);
                    return false;
                } else if(allowNewTags){
                    var value = tagInput.val();
                    if(value != null && value != ''){
                        console.log('in else');
                        addItem(value);
                    }
                }
                return e.keyCode != keyMap.space;
            }else if(e.keyCode == keyMap.backspace){
                // backspace
                if(tagInput.val() == ''){
                    removeLastItem();
                }
                updateTagInputWidth();
            } else {
                updateTagInputWidth();
            }
        });

        tagList.parent().click(function(e){
            tagInput.focus();
        });

        // functions
        function setValue(){
            tagField.val(inserted.join(' '));
        }

        function updateTagInputWidth()
        {
            /*
            * To make tag wrapping behave as expected, dynamically adjust
            * the tag input's width to its content's width
            * The best way to get the content's width in pixels is to add it
            * to the DOM, grab the width, then remove it from the DOM.
            */
            var temp = $("").text(tagInput.val()).appendTo(inputItem);
            var width = temp.width();
            temp.remove();
            tagInput.width(width + 20);
        }

        function addItem(value, focus){
            console.log('added value' + value);
            value = value.trim();
            var index = $.inArray(value,tagstmp);
            if(($.inArray(value,inserted) == -1) && ( index > -1 || allowNewTags)){
                //delete from tags
                if(index >-1){
                    tagstmp.splice(index,1);
                }
                inserted.push(value);
                inputItem.before("
" + value + " x
");
                tagInput.val("");
                currentValue = null;
                currentItem = null;
                // add remove click event
                var new_index = tagList.children('.superblyTagItem').size()-1;
                $(tagList.children('.superblyTagItem')[new_index]).children('a').click(function(e){
                    var value = $($(this).parent('.superblyTagItem').children('span')[0]).text();
                    removeItem(value);
                });
            }
            suggestList.css('display', 'none');
            updateTagInputWidth();
            setValue();
            if(focus === undefined || focus)
                tagInput.focus();
        }

        function removeItem(value){
            var index = $.inArray(value,tags);
            var tmpIndex = $.inArray(value,tagstmp);
            if(index > -1 && tmpIndex == -1){
                tagstmp.push(value);
            }
            index = $.inArray(value,inserted);
            if(index > -1){
                inserted.splice(index,1);
                tagList.children(".superblyTagItem").filter(function(){return $('span', this).html() == value;}).remove();
            }
            tagstmp.sort();
            tagInput.focus();
            setValue();
        }

        function removeLastItem(){
            var last_index = inserted.length-1;
            var last_value = inserted[last_index];
            removeItem(last_value);
        }

        function getSuggestionsArray(value){
            var suggestions = new Array();
            var count = 0;
            for(key in tagstmp){
                if(showTagsNumber <= count){
                    break;
                }
                // if beginning is same
                var lower_case_tag = tagstmp[key].toLocaleLowerCase();
                var lower_cast_value = value.toLowerCase();
                if(lower_case_tag.indexOf(lower_cast_value) == 0){
                    suggestions.push(tagstmp[key]);
                    count++;
                }
            }
            return suggestions;
        }

        function suggest(value){
            load_suggestions(value);
        }

        /**
         * Perform an ajax request to the delapi /tags/suggest feauture
         *
         */
        function load_suggestions(value) {
            function callback(tag_list) {
                tags = tag_list;
                tagstmp = tags.slice();

                // now onto what the suggest method wanted to do originally
                suggestList.show();
                if (value == currentValue) {
                    return false;
                }

                currentValue = value;
                suggestList.empty();

                var suggestions = getSuggestionsArray(value);
                for(key in suggestions){
                    suggestList.append("
" + suggestions[key] + "
");
                }

                var suggestionItems = suggestList.children('.superblySuggestItem');

                console.log('binding suggestion items');

                // add click event to suggest items
                // @todo figure out why this click event is never fired
                // the focusout event is fired and that causes it to use a
                // wrong value
                suggestionItems.bind('click', function(e) {
                    console.log('clicked');
                    console.log($(this));
                    addItem($(this).html());
                    e.preventDefault();
                });

                console.log(suggestionItems);

                selectedIndex=null;
                if(!allowNewTags){
                    selectedIndex=0;
                    $(suggestionItems[selectedIndex]).addClass("selected");
                    currentItem = $(suggestionItems[selectedIndex]).html();
                }
            }

            if(value != "" && settings.complete)
                settings.complete(value, callback);
        };

        function selectDown(){
            var suggestions = suggestList.children('.superblySuggestItem');
            var size = suggestions.size();
            if(selectedIndex == null){
                selectedIndex=0;
            }else if(selectedIndex < size-1){
                $(suggestions[selectedIndex]).removeClass("selected");
                selectedIndex++;
            }
            $(suggestions[selectedIndex]).addClass("selected");
            currentItem = $(suggestions[selectedIndex]).html();
        }

        function selectUp(){
            if(selectedIndex == 0){
                selectedIndex=null;
                currentItem = null;
                tagInput.focus();
            } else if(selectedIndex >0){
                var suggestions = suggestList.children('.superblySuggestItem');
                $(suggestions[selectedIndex]).removeClass("selected");
                selectedIndex--;
                $(suggestions[selectedIndex]).addClass("selected");
                currentItem = $(suggestions[selectedIndex]).html();
            }
        }
    }
})(jQuery);
<commit_msg>fix mouse click behavior on tag menu<commit_after>/*!
 * superbly tagfield v0.1
 * http://www.superbly.ch
 *
 * Copyright 2011, Manuel Spierenburg
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://www.superbly.ch/licenses/mit-license.txt
 * http://www.superbly.ch/licenses/gpl-2.0.txt
 *
 * Date: Sun Apr 14 00:47:29 2011 -0500
 */
(function($){
    $.fn.superblyTagField = function(userOptions) {
        var settings = {
            allowNewTags:true,
            showTagsNumber:10,
            preset:[],
            tags:[],
            complete:function() { return []; }
        };

        if(userOptions) {
            $.extend(settings, userOptions);
        }

        superblyTagField(this, settings);

        return this;
    };

    var keyMap = {
        downArrow:40,
        upArrow:38,
        enter:13,
        space:32,
        tab:9,
        backspace:8
    }

    function superblyTagField(tagField, settings) {

        var tags = settings.tags.sort();
        var preset = settings.preset;
        var allowNewTags = settings.allowNewTags;
        var showTagsNumber = settings.showTagsNumber;

        var tagstmp = tags.slice();

        // prepare needed vars
        var inserted = new Array();
        var selectedIndex = null;
        var currentValue = null;
        var currentItem = null;
        var hoverSuggestItems = false;

        tagField.css('display', 'none');

        var superblyMarkup = '

<input class="superblyTagInput" type="text" autocomplete="false">

';
        tagField.after(superblyMarkup);

        var tagInput = $(".superblyTagInput", tagField.next());
        var suggestList = tagInput.next();
        var inputItem = tagInput.parent();
        var tagList = inputItem.parent();

        // set presets
        for(i in preset){
            console.log('preset');
            addItem(preset[i]);
        }

        tagField.change(function() {
            var existingTags = tagField.val().split(/ /);
            for(var t in existingTags) {
                addItem(existingTags[t]);
            }
        });

        // events
        suggestList.mouseover(function(e){
            hoverSuggestItems = true;
        });

        suggestList.mouseleave(function(e){
            hoverSuggestItems = false;
        });

        suggestList.mousedown(function(e) {
            addItem(e.target.innerHTML);
            tagInput.focus();
        });

        tagInput.keyup(function(e){
            suggest($(this).val());
        });

        tagInput.focusout(function(e){
            console.log('hoverSuggestItems');
            console.log(hoverSuggestItems);
            if(!hoverSuggestItems){
                suggestList.css('display', 'none');
            }
            if(allowNewTags){
                var value = tagInput.val();
                if(value != null && value != ''){
                    console.log('focusout');
                    addItem(value, false);
                }
            }
        });

        tagInput.focus(function(e){
            currentValue = null;
        });

        tagInput.keydown(function(e){
            if(e.keyCode == keyMap.downArrow) {
                selectDown();
            }else if(e.keyCode == keyMap.upArrow) {
                selectUp()
            }else if(e.keyCode == keyMap.enter || e.keyCode == keyMap.tab || e.keyCode == keyMap.space) {
                if(currentItem != null){
                    console.log('in if');
                    addItem(currentItem);
                    return false;
                } else if(allowNewTags){
                    var value = tagInput.val();
                    if(value != null && value != ''){
                        console.log('in else');
                        addItem(value);
                    }
                }
                return e.keyCode != keyMap.space;
            }else if(e.keyCode == keyMap.backspace){
                // backspace
                if(tagInput.val() == ''){
                    removeLastItem();
                }
                updateTagInputWidth();
            } else {
                updateTagInputWidth();
            }
        });

        tagList.parent().click(function(e){
            tagInput.focus();
        });

        // functions
        function setValue(){
            tagField.val(inserted.join(' '));
        }

        function updateTagInputWidth()
        {
            /*
            * To make tag wrapping behave as expected, dynamically adjust
            * the tag input's width to its content's width
            * The best way to get the content's width in pixels is to add it
            * to the DOM, grab the width, then remove it from the DOM.
            */
            var temp = $("").text(tagInput.val()).appendTo(inputItem);
            var width = temp.width();
            temp.remove();
            tagInput.width(width + 20);
        }

        function addItem(value, focus){
            console.log('added value' + value);
            value = value.trim();
            var index = $.inArray(value,tagstmp);
            if(($.inArray(value,inserted) == -1) && ( index > -1 || allowNewTags)){
                //delete from tags
                if(index >-1){
                    tagstmp.splice(index,1);
                }
                inserted.push(value);
                inputItem.before("
" + value + " x
");
                tagInput.val("");
                currentValue = null;
                currentItem = null;
                // add remove click event
                var new_index = tagList.children('.superblyTagItem').size()-1;
                $(tagList.children('.superblyTagItem')[new_index]).children('a').click(function(e){
                    var value = $($(this).parent('.superblyTagItem').children('span')[0]).text();
                    removeItem(value);
                });
            }
            suggestList.css('display', 'none');
            updateTagInputWidth();
            setValue();
            if(focus === undefined || focus)
                tagInput.focus();
        }

        function removeItem(value){
            var index = $.inArray(value,tags);
            var tmpIndex = $.inArray(value,tagstmp);
            if(index > -1 && tmpIndex == -1){
                tagstmp.push(value);
            }
            index = $.inArray(value,inserted);
            if(index > -1){
                inserted.splice(index,1);
                tagList.children(".superblyTagItem").filter(function(){return $('span', this).html() == value;}).remove();
            }
            tagstmp.sort();
            tagInput.focus();
            setValue();
        }

        function removeLastItem(){
            var last_index = inserted.length-1;
            var last_value = inserted[last_index];
            removeItem(last_value);
        }

        function getSuggestionsArray(value){
            var suggestions = new Array();
            var count = 0;
            for(key in tagstmp){
                if(showTagsNumber <= count){
                    break;
                }
                // if beginning is same
                var lower_case_tag = tagstmp[key].toLocaleLowerCase();
                var lower_cast_value = value.toLowerCase();
                if(lower_case_tag.indexOf(lower_cast_value) == 0){
                    suggestions.push(tagstmp[key]);
                    count++;
                }
            }
            return suggestions;
        }

        function suggest(value){
            load_suggestions(value);
        }

        /**
         * Perform an ajax request to the delapi /tags/suggest feauture
         *
         */
        function load_suggestions(value) {
            function callback(tag_list) {
                tags = tag_list;
                tagstmp = tags.slice();

                // now onto what the suggest method wanted to do originally
                suggestList.show();
                if (value == currentValue) {
                    return false;
                }

                currentValue = value;
                suggestList.empty();

                var suggestions = getSuggestionsArray(value);
                for(key in suggestions){
                    suggestList.append("
" + suggestions[key] + "
");
                }

                var suggestionItems = suggestList.children('.superblySuggestItem');

                selectedIndex=null;
                if(!allowNewTags){
                    selectedIndex=0;
                    $(suggestionItems[selectedIndex]).addClass("selected");
                    currentItem = $(suggestionItems[selectedIndex]).html();
                }
            }

            if(value != "" && settings.complete)
                settings.complete(value, callback);
        };

        function selectDown(){
            var suggestions = suggestList.children('.superblySuggestItem');
            var size = suggestions.size();
            if(selectedIndex == null){
                selectedIndex=0;
            }else if(selectedIndex < size-1){
                $(suggestions[selectedIndex]).removeClass("selected");
                selectedIndex++;
            }
            $(suggestions[selectedIndex]).addClass("selected");
            currentItem = $(suggestions[selectedIndex]).html();
        }

        function selectUp(){
            if(selectedIndex == 0){
                selectedIndex=null;
                currentItem = null;
                tagInput.focus();
            } else if(selectedIndex >0){
                var suggestions = suggestList.children('.superblySuggestItem');
                $(suggestions[selectedIndex]).removeClass("selected");
                selectedIndex--;
                $(suggestions[selectedIndex]).addClass("selected");
                currentItem = $(suggestions[selectedIndex]).html();
            }
        }
    }
})(jQuery);
<|endoftext|>


<commit_before>/*
 * @author     Alexander Shumilov
 * @copyright  2013-2018 MapCentia ApS
 * @license    http://www.gnu.org/licenses/#AGPL  GNU AFFERO GENERAL PUBLIC LICENSE 3
 */

const React = require('react');
const MapAreaListItem = require('./MapAreaListItem');

/**
 * MapAreaListItem component
 */

class MapAreaList extends React.Component {
    constructor(props) {
        super(props);

        this.mapObj = props.mapObj;
        this.state = {
            areaItems: (props.items ? this.itemsObjectToArray(props.items) : [])
        };
    }

    itemsObjectToArray(propItems) {
        let items = [];
        if (propItems) {
            for (let key in propItems) {
                items.push({
                    id: key,
                    data: propItems[key]
                });
            }
        }

        return items;
    }

    componentWillReceiveProps(nextProps) {
        this.setState({ areaItems: this.itemsObjectToArray(nextProps.items) });
    }

    onRefreshHandler(item) {
        this.props.onMapAreaRefresh(item);
    }

    onDeleteHandler(item) {
        this.props.onMapAreaDelete(item);
    }

    render() {
        if (this.state.areaItems.length === 0) {
            return (
{__("No map areas have been stored yet")}
);
        } else {
            let renderedItems = [];
            this.state.areaItems.map((item, index) => {
                renderedItems.push(<MapAreaListItem
                    onRefresh={this.onRefreshHandler.bind(this, item)}
                    onDelete={this.onDeleteHandler.bind(this, item)}
                    mapObj={this.mapObj}
                    key={index}
                    id={item.key}
                    data={item.data}/>);
            });

            return (

                        {__("Info")}
                        {__("Comment")}
                        {__("Actions")}

{renderedItems}

);
        }
    }
}

module.exports = MapAreaList;<commit_msg>React 17 UNSAFE<commit_after>/*
 * @author     Alexander Shumilov
 * @copyright  2013-2018 MapCentia ApS
 * @license    http://www.gnu.org/licenses/#AGPL  GNU AFFERO GENERAL PUBLIC LICENSE 3
 */

const React = require('react');
const MapAreaListItem = require('./MapAreaListItem');

/**
 * MapAreaListItem component
 */

class MapAreaList extends React.Component {
    constructor(props) {
        super(props);

        this.mapObj = props.mapObj;
        this.state = {
            areaItems: (props.items ? this.itemsObjectToArray(props.items) : [])
        };
    }

    itemsObjectToArray(propItems) {
        let items = [];
        if (propItems) {
            for (let key in propItems) {
                items.push({
                    id: key,
                    data: propItems[key]
                });
            }
        }

        return items;
    }

    UNSAFE_componentWillReceiveProps(nextProps) {
        this.setState({ areaItems: this.itemsObjectToArray(nextProps.items) });
    }

    onRefreshHandler(item) {
        this.props.onMapAreaRefresh(item);
    }

    onDeleteHandler(item) {
        this.props.onMapAreaDelete(item);
    }

    render() {
        if (this.state.areaItems.length === 0) {
            return (
{__("No map areas have been stored yet")}
);
        } else {
            let renderedItems = [];
            this.state.areaItems.map((item, index) => {
                renderedItems.push(<MapAreaListItem
                    onRefresh={this.onRefreshHandler.bind(this, item)}
                    onDelete={this.onDeleteHandler.bind(this, item)}
                    mapObj={this.mapObj}
                    key={index}
                    id={item.key}
                    data={item.data}/>);
            });

            return (

                        {__("Info")}
                        {__("Comment")}
                        {__("Actions")}

{renderedItems}

);
        }
    }
}

module.exports = MapAreaList;<|endoftext|>


<commit_before>/**
 * Created by remy on 01/05/15.
 */

function getCurBattery(callback) {
    var data;
    jQuery.ajax({
        url: "http://idp-api.herokuapp.com/spin/latest/batterij",
        type: "GET",
        dataType: 'json',
        success: function (resultData) {
            callback(resultData);
            //console.log(resultData);
        }, error: function (jqXHR, textStatus, errorThrown) {
            callback(null);
            console.log(errorThrown);
        }
    });
}

function getCurMode(callback) {
    var data;
    jQuery.ajax({
        url: "http://idp-api.herokuapp.com/spin/latest/mode",
        type: "GET",
        dataType: 'json',
        success: function (resultData) {
            callback(resultData);
        }, error: function (jqXHR, textStatus, errorThrown) {
            callback(null);
            console.log(errorThrown);
        }
    });
}

function insertData()
{
    var modus = $(".modus");
    var batterij = $(".batterij");

    getCurBattery(function (data) {
        batterij.each(function () {
             $(this).append("
"+ data +"%
");
        });

    });

   getCurMode(function (modeData) {

        modus.append("
"+ modeData +"
");
    });
}

<commit_msg>fix append<commit_after>/**
 * Created by remy on 01/05/15.
 */

function getCurBattery(callback) {
    var data;
    jQuery.ajax({
        url: "http://idp-api.herokuapp.com/spin/latest/batterij",
        type: "GET",
        dataType: 'json',
        success: function (resultData) {
            callback(resultData);
            //console.log(resultData);
        }, error: function (jqXHR, textStatus, errorThrown) {
            callback(null);
            console.log(errorThrown);
        }
    });
}

function getCurMode(callback) {
    var data;
    jQuery.ajax({
        url: "http://idp-api.herokuapp.com/spin/latest/mode",
        type: "GET",
        dataType: 'json',
        success: function (resultData) {
            callback(resultData);
        }, error: function (jqXHR, textStatus, errorThrown) {
            callback(null);
            console.log(errorThrown);
        }
    });
}

function insertData()
{
    var modus = $(".modus");
    var batterij = $(".batterij");

    getCurBattery(function (data) {
        batterij.each(function () {
             $(this).html("
"+ data +"%
");
        });

    });

   getCurMode(function (modeData) {

        modus.html("
"+ modeData +"
");
    });
}

<|endoftext|>