<commit_before>/**
 * @license
 * Copyright 2015 Google Inc.
 *
 * 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.
 */

describe('StreamingEngine', function() {
  var originalTimeout;

  var metadata = {
    video: {
      initSegmentUri: 'test/assets/sintel-video-init.mp4',
      mvhdOffset: 0x24,
      segmentUri: 'test/assets/sintel-video-segment.mp4',
      tfdtOffset: 0x34,
      segmentDuration: 12,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4; codecs="avc1.42c01e"',
      generator: null,
      segmentSize: null
    },
    audio: {
      initSegmentUri: 'test/assets/sintel-audio-init.mp4',
      mvhdOffset: 0x20,
      segmentUri: 'test/assets/sintel-audio-segment.mp4',
      tfdtOffset: 0x38,
      segmentDuration: 10.005333,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4; codecs="mp4a.40.2"',
      generator: null,
      segmentSize: null
    }
  };

  var presentationDuration = 60;
  var minBufferTime = 2;

  var eventManager;
  var video;
  var timeline;

  var playhead;
  var onBuffering;
  var onSeek;

  var mediaSource;
  var mediaSourceEngine;

  var netEngine;

  var audioStream1;
  var videoStream1;

  var audioStream2;
  var videoStream2;

  var manifest;

  var onCanSwitch;
  var onBufferNewPeriod;
  var onError;
  var onInitialStreamsSetup;
  var onStartupComplete;
  var streamingEngine;

  function createStreamGenerator(type, metadata) {
    var generator = new shaka.test.DashVodStreamGenerator(
        metadata.initSegmentUri, metadata.mvhdOffset,
        metadata.segmentUri, metadata.tfdtOffset, metadata.segmentDuration,
        metadata.presentationTimeOffset, presentationDuration);
    metadata.generator = generator;
    return generator.init();
  }

  beforeAll(function(done) {
    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;  // ms

    video = /** @type {HTMLVideoElement} */ (document.createElement('video'));
    video.width = '600';
    video.height = '400';
    document.body.appendChild(video);

    Promise.all([
      createStreamGenerator('video', metadata.video),
      createStreamGenerator('audio', metadata.audio)
    ]).then(function() {
      metadata.video.segmentSize =
          metadata.video.generator.getSegment(1, 0).byteLength;
      metadata.audio.segmentSize =
          metadata.audio.generator.getSegment(1, 0).byteLength;
    }).catch(fail).then(done);
  });

  beforeEach(function(done) {
    eventManager = new shaka.util.EventManager();
    setupMediaSource().then(setupTest).catch(fail).then(done);
  });

  function setupMediaSource() {
    // Setup MediaSource and MediaSourceEngine.
    mediaSource = new MediaSource();
    video.src = window.URL.createObjectURL(mediaSource);

    var p = new shaka.util.PublicPromise();
    var onMediaSourceOpen = function() {
      eventManager.unlisten(mediaSource, 'sourceopen');
      mediaSource.duration = 0;
      mediaSourceEngine = new shaka.media.MediaSourceEngine(mediaSource, null);
      p.resolve();
    };
    eventManager.listen(mediaSource, 'sourceopen', onMediaSourceOpen);

    return p;
  }

  function setupTest() {
    // Setup PresentationTimeline.
    timeline = createMockPresentationTimeline();

    timeline.getDuration.and.returnValue(presentationDuration);
    timeline.getSegmentAvailabilityStart.and.returnValue(0);
    timeline.getSegmentAvailabilityEnd.and.returnValue(presentationDuration);

    // These methods should not be invoked.
    timeline.setDuration.and.throwError(
        new Error('unexpected call to setDuration()'));
    timeline.getSegmentAvailabilityDuration.and.returnValue(null);

    // Setup Playhead.
    onBuffering = jasmine.createSpy('onBuffering');
    var onSeek = function() { streamingEngine.seeked(); };
    playhead = new shaka.media.Playhead(
        /** @type {!HTMLVideoElement} */(video),
        timeline, minBufferTime, 0, onBuffering, onSeek);

    setupNetworkingEngine();
    setupManifest();
    createStreamingEngine();
  }

  function setupNetworkingEngine() {
    var responseMap = {
      '1_audio_init': metadata.audio.generator.getInitSegment(0),
      '1_video_init': metadata.video.generator.getInitSegment(0),

      '1_audio_1': metadata.audio.generator.getSegment(1, 0),
      '1_audio_2': metadata.audio.generator.getSegment(2, 0),
      '1_audio_3': metadata.audio.generator.getSegment(3, 0),

      '1_video_1': metadata.video.generator.getSegment(1, 0),
      '1_video_2': metadata.video.generator.getSegment(2, 0),
      '1_video_3': metadata.video.generator.getSegment(3, 0),

      '2_audio_init': metadata.audio.generator.getInitSegment(0),
      '2_video_init': metadata.video.generator.getInitSegment(0),

      '2_audio_1': metadata.audio.generator.getSegment(1, 0),
      '2_audio_2': metadata.audio.generator.getSegment(2, 0),
      '2_audio_3': metadata.audio.generator.getSegment(3, 0),

      '2_video_1': metadata.video.generator.getSegment(1, 0),
      '2_video_2': metadata.video.generator.getSegment(2, 0),
      '2_video_3': metadata.video.generator.getSegment(3, 0)
    };
    netEngine = new shaka.test.FakeNetworkingEngine(responseMap);
  }

  function setupManifest() {
    // Functions for findSegmentPosition() and getSegmentReference().
    var find = function(contentType, t) {
      // Note: |t| is relative to a Period's start time.
      return Math.floor(t / metadata[contentType].segmentDuration) + 1;
    };
    var get = makeSegmentReference;

    audioStream1 = createMockAudioStream(0);
    videoStream1 = createMockVideoStream(1);

    // Setup first Period.
    audioStream1.createSegmentIndex.and.returnValue(Promise.resolve());
    videoStream1.createSegmentIndex.and.returnValue(Promise.resolve());

    audioStream1.findSegmentPosition.and.callFake(find.bind(null, 'audio'));
    videoStream1.findSegmentPosition.and.callFake(find.bind(null, 'video'));

    audioStream1.getSegmentReference.and.callFake(get.bind(null, 1, 'audio'));
    videoStream1.getSegmentReference.and.callFake(get.bind(null, 1, 'video'));

    audioStream1.initSegmentReference =
        new shaka.media.InitSegmentReference(['1_audio_init'], 0, null);
    videoStream1.initSegmentReference =
        new shaka.media.InitSegmentReference(['1_video_init'], 0, null);

    // Setup second Period.
    audioStream2 = createMockAudioStream(4);
    videoStream2 = createMockVideoStream(5);

    audioStream2.createSegmentIndex.and.returnValue(Promise.resolve());
    videoStream2.createSegmentIndex.and.returnValue(Promise.resolve());

    audioStream2.findSegmentPosition.and.callFake(find.bind(null, 'audio'));
    videoStream2.findSegmentPosition.and.callFake(find.bind(null, 'video'));

    audioStream2.getSegmentReference.and.callFake(get.bind(null, 2, 'audio'));
    videoStream2.getSegmentReference.and.callFake(get.bind(null, 2, 'video'));

    audioStream2.initSegmentReference =
        new shaka.media.InitSegmentReference(['2_audio_init'], 0, null);
    videoStream2.initSegmentReference =
        new shaka.media.InitSegmentReference(['2_video_init'], 0, null);

    // Create Manifest.
    manifest = {
      presentationTimeline:
          /** @type {!shaka.media.PresentationTimeline} */ (timeline),
      minBufferTime: minBufferTime,
      periods: [
        {
          startTime: 0,
          streamSets: [
            {type: 'audio', streams: [audioStream1]},
            {type: 'video', streams: [videoStream1]}
          ]
        },
        {
          startTime: 30,
          streamSets: [
            {type: 'audio', streams: [audioStream2]},
            {type: 'video', streams: [videoStream2]}
          ]
        }
      ]
    };
  }  // setupManifest()

  function createStreamingEngine() {
    onCanSwitch = jasmine.createSpy('onCanSwitch');
    onBufferNewPeriod = jasmine.createSpy('onBufferNewPeriod');
    onError = jasmine.createSpy('onError');
    onInitialStreamsSetup = jasmine.createSpy('onInitialStreamsSetup');
    onStartupComplete = jasmine.createSpy('onStartupComplete');

    var config = {
      rebufferingGoal: 2,
      bufferingGoal: 5,
      retryParameters: shaka.net.NetworkingEngine.defaultRetryParameters(),
      byteLimit: 2 * 1000 * 1000  // 2MB
    };
    streamingEngine = new shaka.media.StreamingEngine(
        playhead, mediaSourceEngine, netEngine, manifest,
        onCanSwitch, onBufferNewPeriod, onError,
        onInitialStreamsSetup, onStartupComplete);
    streamingEngine.configure(config);
  }

  afterEach(function(done) {
    // Note: each test is responsible for destroying the StreamingEngine
    // instance.
    mediaSourceEngine.destroy().then(function() {
      video.src = '';
      return playhead.destroy();
    }).then(function() {
      return eventManager.destroy();
    }).catch(fail).then(done);
  });

  afterAll(function() {
    document.body.removeChild(video);
    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
  });

  it('plays', function(done) {
    onStartupComplete.and.callFake(function() {
      video.play();
    });

    onBufferNewPeriod.and.callFake(function(period) {
      expect(period).toBe(manifest.periods[1]);
      streamingEngine.switch('audio', audioStream2);
      streamingEngine.switch('video', videoStream2);
    });

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  it('plays at high playback rates', function(done) {
    var startupComplete = false;

    onStartupComplete.and.callFake(function() {
      startupComplete = true;
      video.play();
    });

    onBuffering.and.callFake(function(buffering) {
      if (!buffering) {
        expect(startupComplete).toBeTruthy();
        video.playbackRate = 10;
      }
    });

    onBufferNewPeriod.and.callFake(function(period) {
      expect(period).toBe(manifest.periods[1]);
      streamingEngine.switch('audio', audioStream2);
      streamingEngine.switch('video', videoStream2);
    });

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  it('can handle buffered seeks', function(done) {
    onStartupComplete.and.callFake(function() {
      video.play();
    });

    onBufferNewPeriod.and.callFake(function(period) {
      if (period == manifest.periods[0]) {
        streamingEngine.switch('audio', audioStream1);
        streamingEngine.switch('video', videoStream1);
      } else {
        streamingEngine.switch('audio', audioStream2);
        streamingEngine.switch('video', videoStream2);
      }
    });

    // After 35 seconds seek back 10 seconds into the first Period.
    var onTimeUpdate = function() {
      if (video.currentTime >= 35) {
        eventManager.unlisten(video, 'timeupdate');
        video.currentTime = 25;
      }
    };
    eventManager.listen(video, 'timeupdate', onTimeUpdate);

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  it('can handle unbuffered seeks', function(done) {
    onStartupComplete.and.callFake(function() {
      video.play();
    });

    onBufferNewPeriod.and.callFake(function(period) {
      expect(period).toBe(manifest.periods[1]);
      streamingEngine.switch('audio', audioStream2);
      streamingEngine.switch('video', videoStream2);
    });

    // After 20 seconds seek 10 seconds into the second Period.
    var onTimeUpdate = function() {
      if (video.currentTime >= 20) {
        eventManager.unlisten(video, 'timeupdate');
        video.currentTime = 40;
      }
    };
    eventManager.listen(video, 'timeupdate', onTimeUpdate);

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  /**
   * Constructs a SegmentReference with a test URI.
   * @param {number} period The Period number (one-based).
   * @param {string} contentType The content type.
   * @param {number} position The segment's position (one-based).
   */
  function makeSegmentReference(period, contentType, position) {
    if (position > 3) return null;
    var duration = metadata[contentType].segmentDuration;
    var size = metadata[contentType].segmentSize;
    return new shaka.media.SegmentReference(
        position, (position - 1) * duration, position * duration,
        ['' + period + '_' + contentType + '_' + position],
        0, size);
  }

  function createMockNetworkingEngine() {
    return {
      destroy: jasmine.createSpy('destroy'),
      request: jasmine.createSpy('request')
    };
  }

  function createMockPresentationTimeline() {
    return {
      getDuration: jasmine.createSpy('getDuration'),
      setDuration: jasmine.createSpy('setDuration'),
      getSegmentAvailabilityDuration:
          jasmine.createSpy('getSegmentAvailabilityDuration'),
      getSegmentAvailabilityStart:
          jasmine.createSpy('getSegmentAvailabilityStart'),
      getSegmentAvailabilityEnd:
          jasmine.createSpy('getSegmentAvailabilityEnd')
    };
  }

  function createMockAudioStream(id) {
    return {
      id: id,
      createSegmentIndex: jasmine.createSpy('createSegmentIndex'),
      findSegmentPosition: jasmine.createSpy('findSegmentPosition'),
      getSegmentReference: jasmine.createSpy('getSegmentReference'),
      initSegmentReference: null,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codecs: 'mp4a.40.2',
      bandwidth: 192000
    };
  }

  function createMockVideoStream(id) {
    return {
      id: id,
      createSegmentIndex: jasmine.createSpy('createSegmentIndex'),
      findSegmentPosition: jasmine.createSpy('findSegmentPosition'),
      getSegmentReference: jasmine.createSpy('getSegmentReference'),
      initSegmentReference: null,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codecs: 'avc1.42c01e',
      bandwidth: 5000000,
      width: 600,
      height: 400
    };
  }
});

<commit_msg>Mute StreamingEngine integration tests<commit_after>/**
 * @license
 * Copyright 2015 Google Inc.
 *
 * 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.
 */

describe('StreamingEngine', function() {
  var originalTimeout;

  var metadata = {
    video: {
      initSegmentUri: 'test/assets/sintel-video-init.mp4',
      mvhdOffset: 0x24,
      segmentUri: 'test/assets/sintel-video-segment.mp4',
      tfdtOffset: 0x34,
      segmentDuration: 12,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4; codecs="avc1.42c01e"',
      generator: null,
      segmentSize: null
    },
    audio: {
      initSegmentUri: 'test/assets/sintel-audio-init.mp4',
      mvhdOffset: 0x20,
      segmentUri: 'test/assets/sintel-audio-segment.mp4',
      tfdtOffset: 0x38,
      segmentDuration: 10.005333,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4; codecs="mp4a.40.2"',
      generator: null,
      segmentSize: null
    }
  };

  var presentationDuration = 60;
  var minBufferTime = 2;

  var eventManager;
  var video;
  var timeline;

  var playhead;
  var onBuffering;
  var onSeek;

  var mediaSource;
  var mediaSourceEngine;

  var netEngine;

  var audioStream1;
  var videoStream1;

  var audioStream2;
  var videoStream2;

  var manifest;

  var onCanSwitch;
  var onBufferNewPeriod;
  var onError;
  var onInitialStreamsSetup;
  var onStartupComplete;
  var streamingEngine;

  function createStreamGenerator(type, metadata) {
    var generator = new shaka.test.DashVodStreamGenerator(
        metadata.initSegmentUri, metadata.mvhdOffset,
        metadata.segmentUri, metadata.tfdtOffset, metadata.segmentDuration,
        metadata.presentationTimeOffset, presentationDuration);
    metadata.generator = generator;
    return generator.init();
  }

  beforeAll(function(done) {
    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;  // ms

    video = /** @type {HTMLVideoElement} */ (document.createElement('video'));
    video.width = '600';
    video.height = '400';
    video.muted = true;
    document.body.appendChild(video);

    Promise.all([
      createStreamGenerator('video', metadata.video),
      createStreamGenerator('audio', metadata.audio)
    ]).then(function() {
      metadata.video.segmentSize =
          metadata.video.generator.getSegment(1, 0).byteLength;
      metadata.audio.segmentSize =
          metadata.audio.generator.getSegment(1, 0).byteLength;
    }).catch(fail).then(done);
  });

  beforeEach(function(done) {
    eventManager = new shaka.util.EventManager();
    setupMediaSource().then(setupTest).catch(fail).then(done);
  });

  function setupMediaSource() {
    // Setup MediaSource and MediaSourceEngine.
    mediaSource = new MediaSource();
    video.src = window.URL.createObjectURL(mediaSource);

    var p = new shaka.util.PublicPromise();
    var onMediaSourceOpen = function() {
      eventManager.unlisten(mediaSource, 'sourceopen');
      mediaSource.duration = 0;
      mediaSourceEngine = new shaka.media.MediaSourceEngine(mediaSource, null);
      p.resolve();
    };
    eventManager.listen(mediaSource, 'sourceopen', onMediaSourceOpen);

    return p;
  }

  function setupTest() {
    // Setup PresentationTimeline.
    timeline = createMockPresentationTimeline();

    timeline.getDuration.and.returnValue(presentationDuration);
    timeline.getSegmentAvailabilityStart.and.returnValue(0);
    timeline.getSegmentAvailabilityEnd.and.returnValue(presentationDuration);

    // These methods should not be invoked.
    timeline.setDuration.and.throwError(
        new Error('unexpected call to setDuration()'));
    timeline.getSegmentAvailabilityDuration.and.returnValue(null);

    // Setup Playhead.
    onBuffering = jasmine.createSpy('onBuffering');
    var onSeek = function() { streamingEngine.seeked(); };
    playhead = new shaka.media.Playhead(
        /** @type {!HTMLVideoElement} */(video),
        timeline, minBufferTime, 0, onBuffering, onSeek);

    setupNetworkingEngine();
    setupManifest();
    createStreamingEngine();
  }

  function setupNetworkingEngine() {
    var responseMap = {
      '1_audio_init': metadata.audio.generator.getInitSegment(0),
      '1_video_init': metadata.video.generator.getInitSegment(0),

      '1_audio_1': metadata.audio.generator.getSegment(1, 0),
      '1_audio_2': metadata.audio.generator.getSegment(2, 0),
      '1_audio_3': metadata.audio.generator.getSegment(3, 0),

      '1_video_1': metadata.video.generator.getSegment(1, 0),
      '1_video_2': metadata.video.generator.getSegment(2, 0),
      '1_video_3': metadata.video.generator.getSegment(3, 0),

      '2_audio_init': metadata.audio.generator.getInitSegment(0),
      '2_video_init': metadata.video.generator.getInitSegment(0),

      '2_audio_1': metadata.audio.generator.getSegment(1, 0),
      '2_audio_2': metadata.audio.generator.getSegment(2, 0),
      '2_audio_3': metadata.audio.generator.getSegment(3, 0),

      '2_video_1': metadata.video.generator.getSegment(1, 0),
      '2_video_2': metadata.video.generator.getSegment(2, 0),
      '2_video_3': metadata.video.generator.getSegment(3, 0)
    };
    netEngine = new shaka.test.FakeNetworkingEngine(responseMap);
  }

  function setupManifest() {
    // Functions for findSegmentPosition() and getSegmentReference().
    var find = function(contentType, t) {
      // Note: |t| is relative to a Period's start time.
      return Math.floor(t / metadata[contentType].segmentDuration) + 1;
    };
    var get = makeSegmentReference;

    audioStream1 = createMockAudioStream(0);
    videoStream1 = createMockVideoStream(1);

    // Setup first Period.
    audioStream1.createSegmentIndex.and.returnValue(Promise.resolve());
    videoStream1.createSegmentIndex.and.returnValue(Promise.resolve());

    audioStream1.findSegmentPosition.and.callFake(find.bind(null, 'audio'));
    videoStream1.findSegmentPosition.and.callFake(find.bind(null, 'video'));

    audioStream1.getSegmentReference.and.callFake(get.bind(null, 1, 'audio'));
    videoStream1.getSegmentReference.and.callFake(get.bind(null, 1, 'video'));

    audioStream1.initSegmentReference =
        new shaka.media.InitSegmentReference(['1_audio_init'], 0, null);
    videoStream1.initSegmentReference =
        new shaka.media.InitSegmentReference(['1_video_init'], 0, null);

    // Setup second Period.
    audioStream2 = createMockAudioStream(4);
    videoStream2 = createMockVideoStream(5);

    audioStream2.createSegmentIndex.and.returnValue(Promise.resolve());
    videoStream2.createSegmentIndex.and.returnValue(Promise.resolve());

    audioStream2.findSegmentPosition.and.callFake(find.bind(null, 'audio'));
    videoStream2.findSegmentPosition.and.callFake(find.bind(null, 'video'));

    audioStream2.getSegmentReference.and.callFake(get.bind(null, 2, 'audio'));
    videoStream2.getSegmentReference.and.callFake(get.bind(null, 2, 'video'));

    audioStream2.initSegmentReference =
        new shaka.media.InitSegmentReference(['2_audio_init'], 0, null);
    videoStream2.initSegmentReference =
        new shaka.media.InitSegmentReference(['2_video_init'], 0, null);

    // Create Manifest.
    manifest = {
      presentationTimeline:
          /** @type {!shaka.media.PresentationTimeline} */ (timeline),
      minBufferTime: minBufferTime,
      periods: [
        {
          startTime: 0,
          streamSets: [
            {type: 'audio', streams: [audioStream1]},
            {type: 'video', streams: [videoStream1]}
          ]
        },
        {
          startTime: 30,
          streamSets: [
            {type: 'audio', streams: [audioStream2]},
            {type: 'video', streams: [videoStream2]}
          ]
        }
      ]
    };
  }  // setupManifest()

  function createStreamingEngine() {
    onCanSwitch = jasmine.createSpy('onCanSwitch');
    onBufferNewPeriod = jasmine.createSpy('onBufferNewPeriod');
    onError = jasmine.createSpy('onError');
    onInitialStreamsSetup = jasmine.createSpy('onInitialStreamsSetup');
    onStartupComplete = jasmine.createSpy('onStartupComplete');

    var config = {
      rebufferingGoal: 2,
      bufferingGoal: 5,
      retryParameters: shaka.net.NetworkingEngine.defaultRetryParameters(),
      byteLimit: 2 * 1000 * 1000  // 2MB
    };
    streamingEngine = new shaka.media.StreamingEngine(
        playhead, mediaSourceEngine, netEngine, manifest,
        onCanSwitch, onBufferNewPeriod, onError,
        onInitialStreamsSetup, onStartupComplete);
    streamingEngine.configure(config);
  }

  afterEach(function(done) {
    // Note: each test is responsible for destroying the StreamingEngine
    // instance.
    mediaSourceEngine.destroy().then(function() {
      video.src = '';
      return playhead.destroy();
    }).then(function() {
      return eventManager.destroy();
    }).catch(fail).then(done);
  });

  afterAll(function() {
    document.body.removeChild(video);
    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
  });

  it('plays', function(done) {
    onStartupComplete.and.callFake(function() {
      video.play();
    });

    onBufferNewPeriod.and.callFake(function(period) {
      expect(period).toBe(manifest.periods[1]);
      streamingEngine.switch('audio', audioStream2);
      streamingEngine.switch('video', videoStream2);
    });

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  it('plays at high playback rates', function(done) {
    var startupComplete = false;

    onStartupComplete.and.callFake(function() {
      startupComplete = true;
      video.play();
    });

    onBuffering.and.callFake(function(buffering) {
      if (!buffering) {
        expect(startupComplete).toBeTruthy();
        video.playbackRate = 10;
      }
    });

    onBufferNewPeriod.and.callFake(function(period) {
      expect(period).toBe(manifest.periods[1]);
      streamingEngine.switch('audio', audioStream2);
      streamingEngine.switch('video', videoStream2);
    });

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  it('can handle buffered seeks', function(done) {
    onStartupComplete.and.callFake(function() {
      video.play();
    });

    onBufferNewPeriod.and.callFake(function(period) {
      if (period == manifest.periods[0]) {
        streamingEngine.switch('audio', audioStream1);
        streamingEngine.switch('video', videoStream1);
      } else {
        streamingEngine.switch('audio', audioStream2);
        streamingEngine.switch('video', videoStream2);
      }
    });

    // After 35 seconds seek back 10 seconds into the first Period.
    var onTimeUpdate = function() {
      if (video.currentTime >= 35) {
        eventManager.unlisten(video, 'timeupdate');
        video.currentTime = 25;
      }
    };
    eventManager.listen(video, 'timeupdate', onTimeUpdate);

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  it('can handle unbuffered seeks', function(done) {
    onStartupComplete.and.callFake(function() {
      video.play();
    });

    onBufferNewPeriod.and.callFake(function(period) {
      expect(period).toBe(manifest.periods[1]);
      streamingEngine.switch('audio', audioStream2);
      streamingEngine.switch('video', videoStream2);
    });

    // After 20 seconds seek 10 seconds into the second Period.
    var onTimeUpdate = function() {
      if (video.currentTime >= 20) {
        eventManager.unlisten(video, 'timeupdate');
        video.currentTime = 40;
      }
    };
    eventManager.listen(video, 'timeupdate', onTimeUpdate);

    var onEnded = function() {
      // Some browsers may not end at exactly 60 seconds.
      expect(Math.round(video.currentTime)).toBe(60);
      streamingEngine.destroy().catch(fail).then(done);
    };
    eventManager.listen(video, 'ended', onEnded);

    // Let's go!
    var streamsByType = {'audio': audioStream1, 'video': videoStream1};
    streamingEngine.init(streamsByType);
  });

  /**
   * Constructs a SegmentReference with a test URI.
   * @param {number} period The Period number (one-based).
   * @param {string} contentType The content type.
   * @param {number} position The segment's position (one-based).
   */
  function makeSegmentReference(period, contentType, position) {
    if (position > 3) return null;
    var duration = metadata[contentType].segmentDuration;
    var size = metadata[contentType].segmentSize;
    return new shaka.media.SegmentReference(
        position, (position - 1) * duration, position * duration,
        ['' + period + '_' + contentType + '_' + position],
        0, size);
  }

  function createMockNetworkingEngine() {
    return {
      destroy: jasmine.createSpy('destroy'),
      request: jasmine.createSpy('request')
    };
  }

  function createMockPresentationTimeline() {
    return {
      getDuration: jasmine.createSpy('getDuration'),
      setDuration: jasmine.createSpy('setDuration'),
      getSegmentAvailabilityDuration:
          jasmine.createSpy('getSegmentAvailabilityDuration'),
      getSegmentAvailabilityStart:
          jasmine.createSpy('getSegmentAvailabilityStart'),
      getSegmentAvailabilityEnd:
          jasmine.createSpy('getSegmentAvailabilityEnd')
    };
  }

  function createMockAudioStream(id) {
    return {
      id: id,
      createSegmentIndex: jasmine.createSpy('createSegmentIndex'),
      findSegmentPosition: jasmine.createSpy('findSegmentPosition'),
      getSegmentReference: jasmine.createSpy('getSegmentReference'),
      initSegmentReference: null,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codecs: 'mp4a.40.2',
      bandwidth: 192000
    };
  }

  function createMockVideoStream(id) {
    return {
      id: id,
      createSegmentIndex: jasmine.createSpy('createSegmentIndex'),
      findSegmentPosition: jasmine.createSpy('findSegmentPosition'),
      getSegmentReference: jasmine.createSpy('getSegmentReference'),
      initSegmentReference: null,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codecs: 'avc1.42c01e',
      bandwidth: 5000000,
      width: 600,
      height: 400
    };
  }
});

<|endoftext|>


<commit_before>/*jslint node: true, indent: 2, unused: true, maxlen: 80, camelcase: true */
/*
 * stompit
 * Copyright (c) 2014 Graham Daws <graham.daws@gmail.com>
 * MIT licensed
 */

var NullWritable = require('../util/NullWritable');
var assign = require('object-assign');

function Subscription(id, ack, onMessageCallback, client) {

  this._id = id;
  this._ack = ack;
  this._onMessageCallback = onMessageCallback;
  this._client = client;
  this._unacknowledged = [];
  this._unsubscribing = false;

  var self = this;

  function getAckHeaders(message) {
    return {
      'subscription': id,
      'message-id': message.headers['message-id'],
      'id': message.headers.ack
    };
  }

  switch(ack) {

    case 'auto':

      this._sendAck = function(unused1, unused2, callback) {

        self._unacknowledged = [];

        if (typeof callback === 'function') {
          process.nextTick(callback);
        }
      };

      break;

    case 'client':

      this._sendAck = function() {

        // Send an acknowledgement frame for a batch of consecutive processed
        // messages at the front of the received message queue.

        var unacknowledged = self._unacknowledged;

        var length = unacknowledged.length;
        if (length < 1) {
          return;
        }

        var type = unacknowledged[0].ackType;
        if (type === undefined) {
          return;
        }

        var end = 1;
        for (; end < length && unacknowledged[end].ackType === type; end++);

        var lastMessage = unacknowledged[end - 1];

        unacknowledged.splice(0, end);

        if ( unacknowledged.length > 0 &&
             unacknowledged[0].ackType !== undefined) {

          process.nextTick(self._sendAck.bind(self, null, null, callback));
        }

        client.sendFrame(type, getAckHeaders(lastMessage)).end();
      };

      break;

    case 'client-individual':

      this._sendAck = function(type, message, callback) {

        var index = self._unacknowledged.indexOf(message);

        if (index !== -1) {

          self._unacknowledged.splice(index, 1);

          var sendOptions = {};

          if (typeof callback === 'function') {
            sendOptions.onReceipt = callback;
            sendOptions.onError = callback;
          }

          client.sendFrame(type, getAckHeaders(message), sendOptions).end();
        }
      };

      break;

    default:
      throw this.createProtocolError('unknown ack mode');
  }
}

Subscription.prototype.getId = function() {
  return this._id;
};

Subscription.prototype._createMessageObject = function(frame) {

  if (!frame) {
    return;
  }

  var self = this;

  var createAckFunction = function(type) {
    return function(callback) {
      this.ackType = type;
      self._sendAck(type, this, callback);
    };
  };

  frame.ack = createAckFunction('ACK');
  frame.nack = createAckFunction('NACK');

  this._unacknowledged.push(frame);

  return frame;
};

Subscription.prototype.processMessageFrame = function(error, frame) {

  if ( this._unsubscribing ||
      (this._client._disconnecting && this._ack !== 'auto') ) {

    if (frame) {
      frame.pipe(new NullWritable());
    }

    return;
  }

  this._onMessageCallback.call(
    this, error, this._createMessageObject(frame), this
  );
};

Subscription.prototype.unsubscribe = function(headers) {

  if (this._unsubscribing) {
    return;
  }

  var self = this;

  this._unsubscribing = true;

  // Prevent ACK or NACK frames being sent after unsubscribe
  this._sendAck = function(unused1, unused2, callback) {

    if (typeof callback === 'function') {

      if (this._ack === 'auto') {
        process.nextTick(callback);
      }
      else {
        process.nextTick(function() {
          callback(new Error('subscription closed'));
        });
      }
    }
  };

  headers = assign({}, headers, {
    'id': this._id
  });

  this._client.sendFrame('UNSUBSCRIBE', headers, {
    onReceipt: function() {
      delete self._client._subscriptions[self._id];
    }
  }).end();
};

module.exports = Subscription;
<commit_msg>The parameter of 'client-individual' ack function can either be a callback function or a sentOptions object<commit_after>/*jslint node: true, indent: 2, unused: true, maxlen: 80, camelcase: true */
/*
 * stompit
 * Copyright (c) 2014 Graham Daws <graham.daws@gmail.com>
 * MIT licensed
 */

var NullWritable = require('../util/NullWritable');
var assign = require('object-assign');

function Subscription(id, ack, onMessageCallback, client) {

  this._id = id;
  this._ack = ack;
  this._onMessageCallback = onMessageCallback;
  this._client = client;
  this._unacknowledged = [];
  this._unsubscribing = false;

  var self = this;

  function getAckHeaders(message) {
    return {
      'subscription': id,
      'message-id': message.headers['message-id'],
      'id': message.headers.ack
    };
  }

  switch(ack) {

    case 'auto':

      this._sendAck = function(unused1, unused2, callback) {

        self._unacknowledged = [];

        if (typeof callback === 'function') {
          process.nextTick(callback);
        }
      };

      break;

    case 'client':

      this._sendAck = function() {

        // Send an acknowledgement frame for a batch of consecutive processed
        // messages at the front of the received message queue.

        var unacknowledged = self._unacknowledged;

        var length = unacknowledged.length;
        if (length < 1) {
          return;
        }

        var type = unacknowledged[0].ackType;
        if (type === undefined) {
          return;
        }

        var end = 1;
        for (; end < length && unacknowledged[end].ackType === type; end++);

        var lastMessage = unacknowledged[end - 1];

        unacknowledged.splice(0, end);

        if ( unacknowledged.length > 0 &&
             unacknowledged[0].ackType !== undefined) {

          process.nextTick(self._sendAck.bind(self, null, null, callback));
        }

        client.sendFrame(type, getAckHeaders(lastMessage)).end();
      };

      break;

    case 'client-individual':

      this._sendAck = function(type, message, callback) {

        var index = self._unacknowledged.indexOf(message);

        if (index !== -1) {

          self._unacknowledged.splice(index, 1);

          var sendOptions = {};

          if (typeof callback === 'function') {
            sendOptions.onReceipt = callback;
            sendOptions.onError = callback;
          }
          else if (typeof callback === 'object') {
            sendOptions = assign(callback, sendOptions);
          }

          client.sendFrame(type, getAckHeaders(message), sendOptions).end();
        }
      };

      break;

    default:
      throw this.createProtocolError('unknown ack mode');
  }
}

Subscription.prototype.getId = function() {
  return this._id;
};

Subscription.prototype._createMessageObject = function(frame) {

  if (!frame) {
    return;
  }

  var self = this;

  var createAckFunction = function(type) {
    return function(callback) {
      this.ackType = type;
      self._sendAck(type, this, callback);
    };
  };

  frame.ack = createAckFunction('ACK');
  frame.nack = createAckFunction('NACK');

  this._unacknowledged.push(frame);

  return frame;
};

Subscription.prototype.processMessageFrame = function(error, frame) {

  if ( this._unsubscribing ||
      (this._client._disconnecting && this._ack !== 'auto') ) {

    if (frame) {
      frame.pipe(new NullWritable());
    }

    return;
  }

  this._onMessageCallback.call(
    this, error, this._createMessageObject(frame), this
  );
};

Subscription.prototype.unsubscribe = function(headers) {

  if (this._unsubscribing) {
    return;
  }

  var self = this;

  this._unsubscribing = true;

  // Prevent ACK or NACK frames being sent after unsubscribe
  this._sendAck = function(unused1, unused2, callback) {

    if (typeof callback === 'function') {

      if (this._ack === 'auto') {
        process.nextTick(callback);
      }
      else {
        process.nextTick(function() {
          callback(new Error('subscription closed'));
        });
      }
    }
  };

  headers = assign({}, headers, {
    'id': this._id
  });

  this._client.sendFrame('UNSUBSCRIBE', headers, {
    onReceipt: function() {
      delete self._client._subscriptions[self._id];
    }
  }).end();
};

module.exports = Subscription;
<|endoftext|>


<commit_before>/**
 * article: http://www.alloyteam.com/2016/10/implement-a-simple-template-engine/
 * code: https://github.com/JuneAndGreen/treasure-box/blob/master/template_engine/string_base/src/tpl.js
 * 变量： {{}}
 */

const parseTpl = (() => {
  /**
   * 默认过滤器
   */
  const defaultFilter = {
    // 防注入
    escape: (str) => {
      let escapeMap = {
        '<': '<',
        '>': '>',
        '&': '&',
        ' ': ' ',
        '"': '"',
        "'": ''',
        '\n': '
',
        '\r': ''
      };

      return str.replace(/\<|\>|\&|\r|\n|\s|\'|\"/g, (one) => escapeMap[one]);
    }
  };

  /**
   * 解析模板
   * @param  {string} content 模板字符串
   * @param  {object} data    模板所需变量
   * @param  {object} filter  过滤器
   * @return {function}       调用执行方法
   */
  const doParseTpl = (content, data, filter) => {

    // 初始化模板处理
    content = content.replace(/\t/g, '  ').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
    let [out, struct] = [[], [
      'try { var OUT = [];',
      '', // 模板生成器占位符
      'return OUT.join(\'\');} catch(e) { throw e; }'
    ]];

    // 初始化模板变量
    let vars = [];
    Object.keys(data).forEach((name) => {
      vars.push(`var ${name} = DATA['${name}'];`);
    });
    out.push(vars.join(''));

    // 初始化过滤器
    let filters = ['var FILTERS = {};'];
    Object.keys(filter).forEach((name) => {
      if (typeof filter[name] === 'function') {
        filters.push(`FILTERS['${name}'] = FILTER['${name}'];`);
      }
    });
    out.push(filters.join(''));

    // 返回方法传入两个参数 DATA以及FILTER
    return new Function('DATA', 'FILTER', struct.join(''));
  }

  /**
   * 返回函数
   */
  return (content, data, filter) => {
    try {
      data = data || {};
      filter = Object.assign({}, defaultFilter, filter);
      const f = doParseTpl(content, data, filter);
      return f(data, filter);
    } catch (e) {
      throw new Error('parse Error,please try again!')
    }
  }
})();
<commit_msg>use another pc<commit_after>/**
 * article: http://www.alloyteam.com/2016/10/implement-a-simple-template-engine/
 * code: https://github.com/JuneAndGreen/treasure-box/blob/master/template_engine/string_base/src/tpl.js
 * 变量： {{}}
 */

const parseTpl = (() => {
  /**
   * 默认过滤器
   */
  const defaultFilter = {
    // 防注入
    escape: (str) => {
      let escapeMap = {
        '<': '<',
        '>': '>',
        '&': '&',
        ' ': ' ',
        '"': '"',
        "'": ''',
        '\n': '
',
        '\r': ''
      };

      return str.replace(/\<|\>|\&|\r|\n|\s|\'|\"/g, (one) => escapeMap[one]);
    }
  };

  /**
   * 解析模板
   * @param  {string} content 模板字符串
   * @param  {object} data    模板所需变量
   * @param  {object} filter  过滤器
   * @return {function}       调用执行方法
   */
  const doParseTpl = (content, data, filter) => {

    // 初始化模板处理
    content = content.replace(/\t/g, '  ').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
    let [out, struct] = [[], [
      'try { var OUT = [];',
      '', // 模板生成器占位符
      'return OUT.join(\'\');} catch(e) { throw e; }'
    ]];

    // 初始化模板变量
    let vars = [];
    Object.keys(data).forEach((name) => {
      vars.push(`var ${name} = DATA['${name}'];`);
    });
    out.push(vars.join(''));

    // 初始化过滤器
    let filters = ['var FILTERS = {};'];
    Object.keys(filter).forEach((name) => {
      if (typeof filter[name] === 'function') {
        filters.push(`FILTERS['${name}'] = FILTER['${name}'];`);
      }
    });
    out.push(filters.join(''));

    // 返回方法传入两个参数 DATA以及FILTER
    return new Function('DATA', 'FILTER', struct.join(''));
  }

  /**
   * 返回函数
   */
  return (content, data, filter) => {
    try {
      data = data || {};
      filter = Object.assign({}, defaultFilter, filter);
      const f = doParseTpl(content, data, filter);
      return f(data, filter);
    } catch (e) {
      throw new Error('parse Error,please try again!')
    }
  }
})();

export default parseTpl;
<|endoftext|>


<commit_before>function createfg(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}
function insertHtml(title, content, type) {
    var attention = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="none" stroke="#FBB03B" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M50,83v2 M50,14v54"/></svg>';
    var error = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#C1272D" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M8.8,90.7L90,9 M90,90.7 L8.8,9"/></svg>';
    var succes = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#8CC63F" stroke-miterlimit="10" d="M46.6,64.3l33.7-40L47.4,75.4L24.7,56L46.6,64.3z" /></svg>';
    var svg = '';
    if (type == 'succes') {
        svg = succes;
    } else if (type == 'error') {
        svg = error;
    } else {
        svg = attention;
    }

    var htmlStr = '

' + svg + '
' + title + '

' + content + '
OK

';
    var fragment = createfg(htmlStr);

    document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function insertCss(){

var cssStr="";
var fragment = createfg(cssStr);

document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function animateSvg(elem ,dir , type) {
    var path = document.getElementById(elem);
    var length = path.getTotalLength();
   if (type=='succes') { path.style.strokeDashoffset = (dir)?0:170;}
   else if (type=='error') { path.style.transform='rotate(720deg)';}
   else if (type=='attention') {}
   	else{};
}

function openModal(type){
   el = document.getElementById("overlay");
     mod = document.getElementById("modalcontainer");
    el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
    el.style.opacity = 1;
    mod.style.width = '450px';
    mod.style.height = '300px';
    setTimeout('document.getElementById("closeModal").style.opacity = 1; ', 500);
    setTimeout(function() {animateSvg('svgico', true,type) ;} , 400);
   // animateSvg('svgico' , true);
}

function closeModal(type){
  var el = document.getElementById("overlay");
    var  mod = document.getElementById("modalcontainer");
    mod.style.width = '400px';
    mod.style.height = '250px';
    el.style.opacity = 0;
    document.getElementById("closeModal").style.opacity = 0;
    setTimeout('el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";', 500);
     animateSvg('svgico' , false , type);
}

function prettytalert(title, content, type){

insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
 	window.onload = function()
{
document.getElementById('closeModal').onclick = function () {
   closeModal(type);
}};

}

function praltimer(title, content, type, time){
insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
	setTimeout(function(){	closeModal(type);
 	},time);
}<commit_msg>Prevent default<commit_after>function createfg(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}
function insertHtml(title, content, type) {
    var attention = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="none" stroke="#FBB03B" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M50,83v2 M50,14v54"/></svg>';
    var error = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#C1272D" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M8.8,90.7L90,9 M90,90.7 L8.8,9"/></svg>';
    var succes = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#8CC63F" stroke-miterlimit="10" d="M46.6,64.3l33.7-40L47.4,75.4L24.7,56L46.6,64.3z" /></svg>';
    var svg = '';
    if (type == 'succes') {
        svg = succes;
    } else if (type == 'error') {
        svg = error;
    } else {
        svg = attention;
    }

    var htmlStr = '

' + svg + '
' + title + '

' + content + '
OK

';
    var fragment = createfg(htmlStr);

    document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function insertCss(){

var cssStr="";
var fragment = createfg(cssStr);

document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function animateSvg(elem ,dir , type) {
    var path = document.getElementById(elem);
    var length = path.getTotalLength();
   if (type=='succes') { path.style.strokeDashoffset = (dir)?0:170;}
   else if (type=='error') { path.style.transform='rotate(720deg)';}
   else if (type=='attention') {}
   	else{};
}

function openModal(type){
   el = document.getElementById("overlay");
     mod = document.getElementById("modalcontainer");
    el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
    el.style.opacity = 1;
    mod.style.width = '450px';
    mod.style.height = '300px';
    setTimeout('document.getElementById("closeModal").style.opacity = 1; ', 500);
    setTimeout(function() {animateSvg('svgico', true,type) ;} , 400);
   // animateSvg('svgico' , true);
}

function closeModal(type){
  var el = document.getElementById("overlay");
    var  mod = document.getElementById("modalcontainer");
    mod.style.width = '400px';
    mod.style.height = '250px';
    el.style.opacity = 0;
    document.getElementById("closeModal").style.opacity = 0;
    setTimeout('el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";', 500);
     animateSvg('svgico' , false , type);
}

function prettytalert(title, content, type){

insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
 	window.onload = function()
{
document.getElementById('closeModal').onclick = function (event) {
	event.preventDefault();
   closeModal(type);
}};

}

function praltimer(title, content, type, time){
insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
	setTimeout(function(){	closeModal(type);
 	},time);
}<|endoftext|>


<commit_before>"use strict";
var errors = require('./errors');

var HttpRequest = function (http, path, method, headers, data, options, cb) {
	this.http = http;
	this.options = options || {};
	this.path = path;
	this.method = method;
	this.headers = headers || {};
	this.data = data;
	this.cb = cb;

	this.url = null;
	this.body = null;
	this.transport = null;
	this.isAborted = false;
	this.timeout = null;
};

HttpRequest.prototype.methodHttpHeaderName = 'X-Method';
HttpRequest.prototype.authHttpHeaderName = 'X-Auth';
HttpRequest.prototype.authExpectedHttpHeaderName = 'X-AuthExpected';
HttpRequest.prototype.authRenewalHttpHeaderName = 'X-AuthRenewal';
HttpRequest.prototype.authRenewalIssuedHttpHeaderName = 'X-AuthRenewalIssued';
HttpRequest.prototype.authRenewalMaxAgeHttpHeaderName = 'X-AuthRenewalMaxAge';

HttpRequest.prototype.headersUrlKey = 'headers';
HttpRequest.prototype.bodyUrlKey = 'body';
HttpRequest.prototype.xdomainUrlKey = 'xdomain';

HttpRequest.prototype.defaultContentType = 'application/json';

HttpRequest.prototype.send = function () {
	this.createTimeout();
	this.url = this.createUrl();
	this.body = this.createBody();
	this.transport = this.createTransport();
	this.createCallback();
	this.sendInternal();
	return this;
};

HttpRequest.prototype.abort = function () {
	this.isAborted = true;
	this.clearTimeout();
	if (this.transport != null) {
		this.transport.onreadystatechange = null;
		this.transport.abort();
	}
};

HttpRequest.prototype.createTimeout = function () {
	var timeout = this.options.timeout;
	if (timeout != null) {
		var self = this;
		this.timeout = setTimeout(function () {
			self.handleTimeout();
		}, timeout);
	}
};

HttpRequest.prototype.handleTimeout = function () {
	this.abort();
	this.cb(new errors.TimeoutError());
};

HttpRequest.prototype.clearTimeout = function () {
	if (this.timeout != null) {
		clearTimeout(this.timeout);
	}
};

HttpRequest.prototype.createUrl = function () {
	var result = this.path;
	if (this.http.baseUri) {
		result = this.http.baseUri + this.path;
	}
	return result;
};

HttpRequest.prototype.createBody = function () {
	var result;
	if (this.data === undefined) {
		result = '';
	}
	else {
		result = JSON.stringify(this.data);
	}
	return result;
};

HttpRequest.prototype.createTransport = function () {
	return new XMLHttpRequest();
};

HttpRequest.prototype.createCallback = function () {
	var self = this;
	// NOTE use onload/onerror pair instead of
	// onreadystatechange in future (will break IE8 support)
	this.transport.onreadystatechange = function() {
		if(self.transport.readyState == 4) {
			self.transport.onreadystatechange = null;
			if (self.isNetworkError()) {
				self.handleNetworkError();
			}
			else {
				self.handleResponse();
			}
		}
	};
};

HttpRequest.prototype.isNetworkError = function () {
	// NOTE works incorrectly with file:// protocol
	return !this.transport.status;
};

HttpRequest.prototype.handleNetworkError = function () {
	this.clearTimeout();
	this.cb(new errors.NetworkError());
};

HttpRequest.prototype.sendInternal = function () {
	if (this.method == 'get') {
		this.sendGet();
	}
	else {
		this.sendPost();
	}
};

HttpRequest.prototype.sendGet = function () {
	this.transport.open('GET', this.createGetUrl());
	this.setHttpHeaders();
	this.transport.send();
};

HttpRequest.prototype.createGetUrl = function () {
	var parts = this.createGetUrlParts();
	var result = this.url;
	if (parts.length > 0) {
		result += '?' + parts.join('&');
	}
	return result;
};

HttpRequest.prototype.createGetUrlParts = function (opt_parts) {
	var parts = opt_parts || [];
	if (this.body) {
		parts.push(this.bodyUrlKey + '=' + encodeURIComponent(this.body));
	}
	return parts;
};

HttpRequest.prototype.sendPost = function () {
	var transport = this.transport;
	transport.open('POST', this.url);
	this.setContentTypeHttpHeader();
	this.setMethodHttpHeader();
	this.setHttpHeaders();
	transport.send(this.body);
};

HttpRequest.prototype.setHttpHeaders = function () {
	var headers = this.createHttpHeaders();
	var transport = this.transport;
	for (var k in headers) {
		transport.setRequestHeader(k, headers[k]);
	}
};

HttpRequest.prototype.createHttpHeaders = function () {
	var headers = this.headers;
	var result = headers.http || {};
	delete headers.http;
	if (headers.auth) {
		result[this.authHttpHeaderName] = headers.auth.token;
	}
	if (headers.authExpected) {
		result[this.authExpectedHttpHeaderName] = headers.auth.expected;
	}
	return result;
};

HttpRequest.prototype.setContentTypeHttpHeader = function () {
	var contentType = this.headers.http && this.headers.http['Content-type'] || this.headers.contentType || this.defaultContentType;
	this.transport.setRequestHeader('Content-type', contentType);
};

HttpRequest.prototype.setMethodHttpHeader = function () {
	if (this.method != 'create') {
		this.transport.setRequestHeader(this.methodHttpHeaderName, this.method);
	}
};

HttpRequest.prototype.handleResponse = function () {
	this.clearTimeout();
	var result = this.createResult();
	var err = this.extractError(result);
	if (err != null) {
		this.cb(err);
	}
	else {
		this.cb(null, result);
	}
};

HttpRequest.prototype.createResult = function () {
	var result = {
		headers: this.getResultHeaders(),
		data: this.getResultData()
	};
	var status = this.getResultStatus();
	if (status != null) {
		result.status = status;
	}
	var transport = this.getTransportForResult();
	if (transport != null) {
		result.transport = transport;
	}
	return result;
};

HttpRequest.prototype.getTransportForResult = function () {
	return this.transport;
};

HttpRequest.prototype.getResultStatus = function () {
	return this.transport.status;
};

HttpRequest.prototype.getResultHeaders = function () {
	var result = {};
	var authRenewalToken = this.transport.getResponseHeader(this.authRenewalHttpHeaderName);
	if (authRenewalToken) {
		var renewal = {
			token: authRenewalToken
		};
		result.authRenewal = renewal;
		var issued = this.transport.getResponseHeader(this.authRenewalIssuedHttpHeaderName);
		if (issued) {
			renewal.issued = new Date(issued);
		}
		var maxAge = this.transport.getResponseHeader(this.authRenewalMaxAgeHttpHeaderName);
		if (maxAge) {
			renewal.maxAge = parseInt(maxAge, 10);
		}
	}
	return result;
};

HttpRequest.prototype.getResultData = function () {
	var body = this.getResultBody();
	return body ? JSON.parse(body) : undefined;
};

HttpRequest.prototype.getResultBody = function () {
	return this.transport.responseText;
};

HttpRequest.prototype.extractError = function (result) {
	var status = result.status;
	var err = null;
	if (status != 200 && status != 204) {
		err = new errors.WebError(result);
	}
	return err;
};

module.exports = HttpRequest;
<commit_msg>client fixed to match new auth<commit_after>"use strict";
var errors = require('./errors');

var HttpRequest = function (http, path, method, headers, data, options, cb) {
	this.http = http;
	this.options = options || {};
	this.path = path;
	this.method = method;
	this.headers = headers || {};
	this.data = data;
	this.cb = cb;

	this.url = null;
	this.body = null;
	this.transport = null;
	this.isAborted = false;
	this.timeout = null;
};

HttpRequest.prototype.methodHttpHeaderName = 'X-Method';
HttpRequest.prototype.authHttpHeaderName = 'X-Auth';
HttpRequest.prototype.authExpectedHttpHeaderName = 'X-AuthExpected';
HttpRequest.prototype.authRenewalHttpHeaderName = 'X-AuthRenewal';
HttpRequest.prototype.authRenewalIssuedHttpHeaderName = 'X-AuthRenewalIssued';
HttpRequest.prototype.authRenewalMaxAgeHttpHeaderName = 'X-AuthRenewalMaxAge';

HttpRequest.prototype.headersUrlKey = 'headers';
HttpRequest.prototype.bodyUrlKey = 'body';
HttpRequest.prototype.xdomainUrlKey = 'xdomain';

HttpRequest.prototype.defaultContentType = 'application/json';

HttpRequest.prototype.send = function () {
	this.createTimeout();
	this.url = this.createUrl();
	this.body = this.createBody();
	this.transport = this.createTransport();
	this.createCallback();
	this.sendInternal();
	return this;
};

HttpRequest.prototype.abort = function () {
	this.isAborted = true;
	this.clearTimeout();
	if (this.transport != null) {
		this.transport.onreadystatechange = null;
		this.transport.abort();
	}
};

HttpRequest.prototype.createTimeout = function () {
	var timeout = this.options.timeout;
	if (timeout != null) {
		var self = this;
		this.timeout = setTimeout(function () {
			self.handleTimeout();
		}, timeout);
	}
};

HttpRequest.prototype.handleTimeout = function () {
	this.abort();
	this.cb(new errors.TimeoutError());
};

HttpRequest.prototype.clearTimeout = function () {
	if (this.timeout != null) {
		clearTimeout(this.timeout);
	}
};

HttpRequest.prototype.createUrl = function () {
	var result = this.path;
	if (this.http.baseUri) {
		result = this.http.baseUri + this.path;
	}
	return result;
};

HttpRequest.prototype.createBody = function () {
	var result;
	if (this.data === undefined) {
		result = '';
	}
	else {
		result = JSON.stringify(this.data);
	}
	return result;
};

HttpRequest.prototype.createTransport = function () {
	return new XMLHttpRequest();
};

HttpRequest.prototype.createCallback = function () {
	var self = this;
	// NOTE use onload/onerror pair instead of
	// onreadystatechange in future (will break IE8 support)
	this.transport.onreadystatechange = function() {
		if(self.transport.readyState == 4) {
			self.transport.onreadystatechange = null;
			if (self.isNetworkError()) {
				self.handleNetworkError();
			}
			else {
				self.handleResponse();
			}
		}
	};
};

HttpRequest.prototype.isNetworkError = function () {
	// NOTE works incorrectly with file:// protocol
	return !this.transport.status;
};

HttpRequest.prototype.handleNetworkError = function () {
	this.clearTimeout();
	this.cb(new errors.NetworkError());
};

HttpRequest.prototype.sendInternal = function () {
	if (this.method == 'get') {
		this.sendGet();
	}
	else {
		this.sendPost();
	}
};

HttpRequest.prototype.sendGet = function () {
	this.transport.open('GET', this.createGetUrl());
	this.setHttpHeaders();
	this.transport.send();
};

HttpRequest.prototype.createGetUrl = function () {
	var parts = this.createGetUrlParts();
	var result = this.url;
	if (parts.length > 0) {
		result += '?' + parts.join('&');
	}
	return result;
};

HttpRequest.prototype.createGetUrlParts = function (opt_parts) {
	var parts = opt_parts || [];
	if (this.body) {
		parts.push(this.bodyUrlKey + '=' + encodeURIComponent(this.body));
	}
	return parts;
};

HttpRequest.prototype.sendPost = function () {
	var transport = this.transport;
	transport.open('POST', this.url);
	this.setContentTypeHttpHeader();
	this.setMethodHttpHeader();
	this.setHttpHeaders();
	transport.send(this.body);
};

HttpRequest.prototype.setHttpHeaders = function () {
	var headers = this.createHttpHeaders();
	var transport = this.transport;
	for (var k in headers) {
		transport.setRequestHeader(k, headers[k]);
	}
};

HttpRequest.prototype.createHttpHeaders = function () {
	var headers = this.headers;
	var result = headers.http || {};
	delete headers.http;
	if (headers.auth != null) {
		if (headers.auth.token) {
			result[this.authHttpHeaderName] = headers.auth.token;
			if (headers.auth.expected) {
				result[this.authExpectedHttpHeaderName] = headers.auth.expected;
			}
		}
	}
	return result;
};

HttpRequest.prototype.setContentTypeHttpHeader = function () {
	var contentType = this.headers.http && this.headers.http['Content-type'] || this.headers.contentType || this.defaultContentType;
	this.transport.setRequestHeader('Content-type', contentType);
};

HttpRequest.prototype.setMethodHttpHeader = function () {
	if (this.method != 'create') {
		this.transport.setRequestHeader(this.methodHttpHeaderName, this.method);
	}
};

HttpRequest.prototype.handleResponse = function () {
	this.clearTimeout();
	var result = this.createResult();
	var err = this.extractError(result);
	if (err != null) {
		this.cb(err);
	}
	else {
		this.cb(null, result);
	}
};

HttpRequest.prototype.createResult = function () {
	var result = {
		headers: this.getResultHeaders(),
		data: this.getResultData()
	};
	var status = this.getResultStatus();
	if (status != null) {
		result.status = status;
	}
	var transport = this.getTransportForResult();
	if (transport != null) {
		result.transport = transport;
	}
	return result;
};

HttpRequest.prototype.getTransportForResult = function () {
	return this.transport;
};

HttpRequest.prototype.getResultStatus = function () {
	return this.transport.status;
};

HttpRequest.prototype.getResultHeaders = function () {
	var result = {};
	var authRenewalToken = this.transport.getResponseHeader(this.authRenewalHttpHeaderName);
	if (authRenewalToken) {
		var renewal = {
			token: authRenewalToken
		};
		result.authRenewal = renewal;
		var issued = this.transport.getResponseHeader(this.authRenewalIssuedHttpHeaderName);
		if (issued) {
			renewal.issued = new Date(issued);
		}
		var maxAge = this.transport.getResponseHeader(this.authRenewalMaxAgeHttpHeaderName);
		if (maxAge) {
			renewal.maxAge = parseInt(maxAge, 10);
		}
	}
	return result;
};

HttpRequest.prototype.getResultData = function () {
	var body = this.getResultBody();
	return body ? JSON.parse(body) : undefined;
};

HttpRequest.prototype.getResultBody = function () {
	return this.transport.responseText;
};

HttpRequest.prototype.extractError = function (result) {
	var status = result.status;
	var err = null;
	if (status != 200 && status != 204) {
		err = new errors.WebError(result);
	}
	return err;
};

module.exports = HttpRequest;
<|endoftext|>


<commit_before>/*---------------------------------------------------------
 * OpenERP diagram library
 *---------------------------------------------------------*/

openerp.web_diagram = function (instance) {
var QWeb = instance.web.qweb,
      _t = instance.web._t,
     _lt = instance.web._lt;
instance.web.views.add('diagram', 'instance.web.DiagramView');
instance.web.DiagramView = instance.web.View.extend({
    display_name: _lt('Diagram'),
    searchable: false,
    init: function(parent, dataset, view_id, options) {
        this._super(parent);
        this.set_default_options(options);
        this.view_manager = parent;
        this.dataset = dataset;
        this.model = this.dataset.model;
        this.view_id = view_id;
        this.domain = this.dataset._domain || [];
        this.context = {};
        this.ids = this.dataset.ids;
    },
    start: function() {
        return this.rpc("/web_diagram/diagram/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
    },

    toTitleCase: function(str) {
        return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
    },

    on_loaded: function(result) {

        var self = this;
        if(this.ids && this.ids.length) {
            this.id = this.ids[self.dataset.index || 0];
        }

        this.fields_view = result.fields_view,
        this.view_id = this.fields_view.view_id,
        this.fields = this.fields_view.fields,
        this.nodes = this.fields_view.arch.children[0],
        this.connectors = this.fields_view.arch.children[1],
        this.node = this.nodes.attrs.object,
        this.connector = this.connectors.attrs.object;

        this.$element.html(QWeb.render("DiagramView", this));
        this.$element.addClass(this.fields_view.arch.attrs['class']);

        this.$element.find('div.oe_diagram_pager button[data-pager-action]').click(function() {
            var action = $(this).data('pager-action');
            self.on_pager_action(action);
        });
        this.labels = _.filter(this.fields_view.arch.children, function(label){
        	return label.tag == "label" ;
          });

        this.do_update_pager();

        // New Node,Edge
        this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_node();});

        if(this.id) {
            self.get_diagram_info();
        }

    },

    get_diagram_info: function() {
        var self = this;
        var params = {
            'id': this.id,
            'model': this.model,
            'node': this.node,
            'connector': this.connector,
            'bgcolor': this.nodes.attrs.bgcolor,
            'shape': this.nodes.attrs.shape,
            'src_node': this.connectors.attrs.source,
            'des_node': this.connectors.attrs.destination,
            'label': this.connectors.attrs.label || false,
            'visible_nodes': [],
            'invisible_nodes': [],
            'node_fields': [],
            'connectors': [],
            'connectors_fields': []
        };

        _.each(this.nodes.children, function(child) {
            if(child.attrs.invisible == '1')
                params['invisible_nodes'].push(child.attrs.name);
            else {
                params['visible_nodes'].push(child.attrs.name);
                params['node_fields'].push(self.fields[child.attrs.name]['string']|| this.toTitleCase(child.attrs.name));
            }
        });

        _.each(this.connectors.children, function(conn) {
            params['connectors_fields'].push(self.fields[conn.attrs.name]['string']|| this.toTitleCase(conn.attrs.name));
            params['connectors'].push(conn.attrs.name);
        });

        this.rpc(
            '/web_diagram/diagram/get_diagram_info',params,
            function(result) {
                self.draw_diagram(result);
            }
        );
    },

    get_label : function(){
    	var self = this
    	var html_label = _.each(self.labels,function(label){
    		html_label = "
" + label.attrs.string + "
"
    		self.$element.find('.oe_diagram_diagram_header').append(html_label)
    		self.$element.find('.oe_diagram_diagram_header > p').css('padding-left','5px')
    	})

    },

    on_diagram_loaded: function(record) {
        var id_record = record['id'];
        if(id_record) {
            this.id = id_record;
            this.get_diagram_info();
            this.get_label();
        }
    },

    // Set-up the drawing elements of the diagram
    draw_diagram: function(result) {
        var self = this;
        var res_nodes  = result['nodes'];
        var res_edges  = result['conn'];
        this.parent_field = result.parent_field;
        this.$element.find('h3.oe_diagram_title').text(result.name);

        var id_to_node = {};

        var style = {
            edge_color: "#A0A0A0",
            edge_label_color: "#555",
            edge_label_font_size: 10,
            edge_width: 2,
            edge_spacing: 100,
            edge_loop_radius: 100,

            node_label_color: "#333",
            node_label_font_size: 12,
            node_outline_color: "#333",
            node_outline_width: 1,
            node_selected_color: "#0097BE",
            node_selected_width: 2,
            node_size_x: 110,
            node_size_y: 80,
            connector_active_color: "#FFF",
            connector_radius: 4,

            close_button_radius: 8,
            close_button_color: "#333",
            close_button_x_color: "#FFF",

            gray: "#DCDCDC",
            white: "#FFF",

            viewport_margin: 50
        };

        // remove previous diagram
        var canvas = self.$element.find('div.oe_diagram_diagram')
                             .empty().get(0);

        var r  = new Raphael(canvas, '100%','100%');

        var graph  = new CuteGraph(r,style,canvas.parentNode);

        var confirm_dialog = $('#dialog').dialog({
            autoOpen: false,
            title: _t("Are you sure?") });

        _.each(res_nodes, function(node) {
            var n = new CuteNode(
                graph,
                node.x + 50,  //FIXME the +50 should be in the layout algorithm
                node.y + 50,
                CuteGraph.wordwrap(node.name, 14),
                node.shape === 'rectangle' ? 'rect' : 'circle',
                node.color === 'white' ? style.white : style.gray);

            n.id = node.id;
            id_to_node[node.id] = n;
        });

        _.each(res_edges, function(edge) {
            var e =  new CuteEdge(
                graph,
                CuteGraph.wordwrap(edge.signal, 32),
                id_to_node[edge.s_id],
                id_to_node[edge.d_id] || id_to_node[edge.s_id]  );  //WORKAROUND
            e.id = edge.id;
        });

        CuteNode.double_click_callback = function(cutenode){
            self.edit_node(cutenode.id);
        };
        var i = 0;
        CuteNode.destruction_callback = function(cutenode){
            if(!confirm(_t("Deleting this node cannot be undone.\nIt will also delete all connected transitions.\n\nAre you sure ?"))){
                return $.Deferred().reject().promise();
            }
            return new instance.web.DataSet(self,self.node).unlink([cutenode.id]);
        };
        CuteEdge.double_click_callback = function(cuteedge){
            self.edit_connector(cuteedge.id);
        };

        CuteEdge.creation_callback = function(node_start, node_end){
            return {label:_t("")};
        };
        CuteEdge.new_edge_callback = function(cuteedge){
            self.add_connector(cuteedge.get_start().id,
                               cuteedge.get_end().id,
                               cuteedge);
        };
        CuteEdge.destruction_callback = function(cuteedge){
            if(!confirm(_t("Deleting this transition cannot be undone.\n\nAre you sure ?"))){
                return $.Deferred().reject().promise();
            }
            return new instance.web.DataSet(self,self.connector).unlink([cuteedge.id]);
        };

    },

    // Creates a popup to edit the content of the node with id node_id
    edit_node: function(node_id){
        var self = this;
        var title = _t('Activity');
        var pop = new instance.web.form.FormOpenPopup(self);

        pop.show_element(
                self.node,
                node_id,
                self.context || self.dataset.context,
                {
                    title: _t("Open: ") + title
                }
            );

        pop.on_write.add(function() {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
            });

        var form_fields = [self.parent_field];
        var form_controller = pop.view_form;

        form_controller.on_record_loaded.add_first(function() {
            _.each(form_fields, function(fld) {
                if (!(fld in form_controller.fields)) { return; }
                var field = form_controller.fields[fld];
                field.$input.prop('disabled', true);
                field.$drop_down.unbind();
                field.$menu_btn.unbind();
            });
        });
    },

    // Creates a popup to add a node to the diagram
    add_node: function(){
        var self = this;
        var title = _t('Activity');
        var pop = new instance.web.form.SelectCreatePopup(self);
        pop.select_element(
            self.node,
            {
                title: _t("Create:") + title,
                initial_view: 'form',
                disable_multiple_selection: true
            },
            self.dataset.domain,
            self.context || self.dataset.context
        );
        pop.on_select_elements.add_last(function(element_ids) {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
        });

        var form_controller = pop.view_form;
        var form_fields = [this.parent_field];

        form_controller.on_record_loaded.add_last(function() {
            _.each(form_fields, function(fld) {
                if (!(fld in form_controller.fields)) { return; }
                var field = form_controller.fields[fld];
                field.set_value(self.id);
                field.dirty = true;
            });
        });
    },

    // Creates a popup to edit the connector of id connector_id
    edit_connector: function(connector_id){
        var self = this;
        var title = _t('Transition');
        var pop = new instance.web.form.FormOpenPopup(self);
        pop.show_element(
            self.connector,
            parseInt(connector_id,10),      //FIXME Isn't connector_id supposed to be an int ?
            self.context || self.dataset.context,
            {
                title: _t("Open: ") + title
            }
        );
        pop.on_write.add(function() {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
        });
    },

    // Creates a popup to add a connector from node_source_id to node_dest_id.
    // dummy_cuteedge if not null, will be removed form the graph after the popup is closed.
    add_connector: function(node_source_id, node_dest_id, dummy_cuteedge){
        var self = this;
        var title = _t('Transition');
        var pop = new instance.web.form.SelectCreatePopup(self);

        pop.select_element(
            self.connector,
            {
                title: _t("Create:") + title,
                initial_view: 'form',
                disable_multiple_selection: true
            },
            this.dataset.domain,
            this.context || this.dataset.context
        );

        pop.on_select_elements.add_last(function(element_ids) {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
        });
        // We want to destroy the dummy edge after a creation cancel. This destroys it even if we save the changes.
        // This is not a problem since the diagram is completely redrawn on saved changes.
        pop.$element.bind("dialogbeforeclose",function(){
            if(dummy_cuteedge){
                dummy_cuteedge.remove();
            }
        });

        var form_controller = pop.view_form;

        form_controller.on_record_loaded.add_last(function () {
            form_controller.fields[self.connectors.attrs.source].set_value(node_source_id);
            form_controller.fields[self.connectors.attrs.source].dirty = true;
            form_controller.fields[self.connectors.attrs.destination].set_value(node_dest_id);
            form_controller.fields[self.connectors.attrs.destination].dirty = true;
        });
    },

    on_pager_action: function(action) {
        switch (action) {
            case 'first':
                this.dataset.index = 0;
                break;
            case 'previous':
                this.dataset.previous();
                break;
            case 'next':
                this.dataset.next();
                break;
            case 'last':
                this.dataset.index = this.dataset.ids.length - 1;
                break;
        }
        var loaded = this.dataset.read_index(_.keys(this.fields_view.fields))
                .pipe(this.on_diagram_loaded);
        this.do_update_pager();
        return loaded;
    },

    do_update_pager: function(hide_index) {
        var $pager = this.$element.find('div.oe_diagram_pager');
        var index = hide_index ? '-' : this.dataset.index + 1;
        if(!this.dataset.count) {
            this.dataset.count = this.dataset.ids.length;
        }
        $pager.find('span.oe_pager_index').html(index);
        $pager.find('span.oe_pager_count').html(this.dataset.count);
    },

    do_show: function() {
        this.do_push_state({});
        return $.when(this._super(), this.on_pager_action('reload'));
    }
});
};

// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
<commit_msg>[IMP]improving code to add label only once on load<commit_after>/*---------------------------------------------------------
 * OpenERP diagram library
 *---------------------------------------------------------*/

openerp.web_diagram = function (instance) {
var QWeb = instance.web.qweb,
      _t = instance.web._t,
     _lt = instance.web._lt;
instance.web.views.add('diagram', 'instance.web.DiagramView');
instance.web.DiagramView = instance.web.View.extend({
    display_name: _lt('Diagram'),
    searchable: false,
    init: function(parent, dataset, view_id, options) {
        this._super(parent);
        this.set_default_options(options);
        this.view_manager = parent;
        this.dataset = dataset;
        this.model = this.dataset.model;
        this.view_id = view_id;
        this.domain = this.dataset._domain || [];
        this.context = {};
        this.ids = this.dataset.ids;
    },
    start: function() {
        return this.rpc("/web_diagram/diagram/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
    },

    toTitleCase: function(str) {
        return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
    },

    on_loaded: function(result) {

        var self = this;
        if(this.ids && this.ids.length) {
            this.id = this.ids[self.dataset.index || 0];
        }

        this.fields_view = result.fields_view,
        this.view_id = this.fields_view.view_id,
        this.fields = this.fields_view.fields,
        this.nodes = this.fields_view.arch.children[0],
        this.connectors = this.fields_view.arch.children[1],
        this.node = this.nodes.attrs.object,
        this.connector = this.connectors.attrs.object;

        this.$element.html(QWeb.render("DiagramView", this));
        this.$element.addClass(this.fields_view.arch.attrs['class']);

        this.$element.find('div.oe_diagram_pager button[data-pager-action]').click(function() {
            var action = $(this).data('pager-action');
            self.on_pager_action(action);
        });
        this.labels = _.filter(this.fields_view.arch.children, function(label){
        	return label.tag == "label" ;
          });

        this.do_update_pager();

        // New Node,Edge
        this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_node();});

        if(this.id) {
            self.get_diagram_info();
        }

    },

    get_diagram_info: function() {
        var self = this;
        var params = {
            'id': this.id,
            'model': this.model,
            'node': this.node,
            'connector': this.connector,
            'bgcolor': this.nodes.attrs.bgcolor,
            'shape': this.nodes.attrs.shape,
            'src_node': this.connectors.attrs.source,
            'des_node': this.connectors.attrs.destination,
            'label': this.connectors.attrs.label || false,
            'visible_nodes': [],
            'invisible_nodes': [],
            'node_fields': [],
            'connectors': [],
            'connectors_fields': []
        };

        _.each(this.nodes.children, function(child) {
            if(child.attrs.invisible == '1')
                params['invisible_nodes'].push(child.attrs.name);
            else {
                params['visible_nodes'].push(child.attrs.name);
                params['node_fields'].push(self.fields[child.attrs.name]['string']|| this.toTitleCase(child.attrs.name));
            }
        });

        _.each(this.connectors.children, function(conn) {
            params['connectors_fields'].push(self.fields[conn.attrs.name]['string']|| this.toTitleCase(conn.attrs.name));
            params['connectors'].push(conn.attrs.name);
        });

        this.rpc(
            '/web_diagram/diagram/get_diagram_info',params,
            function(result) {
                self.draw_diagram(result);
            }
        );
    },

    get_label : function(){
    	var self = this
    	if(self.$element.find('.oe_diagram_diagram_header').text() == ""){
	    	_.each(self.labels,function(label){
	    		html_label = "
" + label.attrs.string + "
"
		    	self.$element.find('.oe_diagram_diagram_header').append(html_label)
		    	self.$element.find('.oe_diagram_diagram_header > p').css('padding-left','5px')
	    	})
    	}
    },

    on_diagram_loaded: function(record) {
        var id_record = record['id'];
        if(id_record) {
            this.id = id_record;
            this.get_diagram_info();
            this.get_label();
        }
    },

    // Set-up the drawing elements of the diagram
    draw_diagram: function(result) {
        var self = this;
        var res_nodes  = result['nodes'];
        var res_edges  = result['conn'];
        this.parent_field = result.parent_field;
        this.$element.find('h3.oe_diagram_title').text(result.name);

        var id_to_node = {};

        var style = {
            edge_color: "#A0A0A0",
            edge_label_color: "#555",
            edge_label_font_size: 10,
            edge_width: 2,
            edge_spacing: 100,
            edge_loop_radius: 100,

            node_label_color: "#333",
            node_label_font_size: 12,
            node_outline_color: "#333",
            node_outline_width: 1,
            node_selected_color: "#0097BE",
            node_selected_width: 2,
            node_size_x: 110,
            node_size_y: 80,
            connector_active_color: "#FFF",
            connector_radius: 4,

            close_button_radius: 8,
            close_button_color: "#333",
            close_button_x_color: "#FFF",

            gray: "#DCDCDC",
            white: "#FFF",

            viewport_margin: 50
        };

        // remove previous diagram
        var canvas = self.$element.find('div.oe_diagram_diagram')
                             .empty().get(0);

        var r  = new Raphael(canvas, '100%','100%');

        var graph  = new CuteGraph(r,style,canvas.parentNode);

        var confirm_dialog = $('#dialog').dialog({
            autoOpen: false,
            title: _t("Are you sure?") });

        _.each(res_nodes, function(node) {
            var n = new CuteNode(
                graph,
                node.x + 50,  //FIXME the +50 should be in the layout algorithm
                node.y + 50,
                CuteGraph.wordwrap(node.name, 14),
                node.shape === 'rectangle' ? 'rect' : 'circle',
                node.color === 'white' ? style.white : style.gray);

            n.id = node.id;
            id_to_node[node.id] = n;
        });

        _.each(res_edges, function(edge) {
            var e =  new CuteEdge(
                graph,
                CuteGraph.wordwrap(edge.signal, 32),
                id_to_node[edge.s_id],
                id_to_node[edge.d_id] || id_to_node[edge.s_id]  );  //WORKAROUND
            e.id = edge.id;
        });

        CuteNode.double_click_callback = function(cutenode){
            self.edit_node(cutenode.id);
        };
        var i = 0;
        CuteNode.destruction_callback = function(cutenode){
            if(!confirm(_t("Deleting this node cannot be undone.\nIt will also delete all connected transitions.\n\nAre you sure ?"))){
                return $.Deferred().reject().promise();
            }
            return new instance.web.DataSet(self,self.node).unlink([cutenode.id]);
        };
        CuteEdge.double_click_callback = function(cuteedge){
            self.edit_connector(cuteedge.id);
        };

        CuteEdge.creation_callback = function(node_start, node_end){
            return {label:_t("")};
        };
        CuteEdge.new_edge_callback = function(cuteedge){
            self.add_connector(cuteedge.get_start().id,
                               cuteedge.get_end().id,
                               cuteedge);
        };
        CuteEdge.destruction_callback = function(cuteedge){
            if(!confirm(_t("Deleting this transition cannot be undone.\n\nAre you sure ?"))){
                return $.Deferred().reject().promise();
            }
            return new instance.web.DataSet(self,self.connector).unlink([cuteedge.id]);
        };

    },

    // Creates a popup to edit the content of the node with id node_id
    edit_node: function(node_id){
        var self = this;
        var title = _t('Activity');
        var pop = new instance.web.form.FormOpenPopup(self);

        pop.show_element(
                self.node,
                node_id,
                self.context || self.dataset.context,
                {
                    title: _t("Open: ") + title
                }
            );

        pop.on_write.add(function() {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
            });

        var form_fields = [self.parent_field];
        var form_controller = pop.view_form;

        form_controller.on_record_loaded.add_first(function() {
            _.each(form_fields, function(fld) {
                if (!(fld in form_controller.fields)) { return; }
                var field = form_controller.fields[fld];
                field.$input.prop('disabled', true);
                field.$drop_down.unbind();
                field.$menu_btn.unbind();
            });
        });
    },

    // Creates a popup to add a node to the diagram
    add_node: function(){
        var self = this;
        var title = _t('Activity');
        var pop = new instance.web.form.SelectCreatePopup(self);
        pop.select_element(
            self.node,
            {
                title: _t("Create:") + title,
                initial_view: 'form',
                disable_multiple_selection: true
            },
            self.dataset.domain,
            self.context || self.dataset.context
        );
        pop.on_select_elements.add_last(function(element_ids) {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
        });

        var form_controller = pop.view_form;
        var form_fields = [this.parent_field];

        form_controller.on_record_loaded.add_last(function() {
            _.each(form_fields, function(fld) {
                if (!(fld in form_controller.fields)) { return; }
                var field = form_controller.fields[fld];
                field.set_value(self.id);
                field.dirty = true;
            });
        });
    },

    // Creates a popup to edit the connector of id connector_id
    edit_connector: function(connector_id){
        var self = this;
        var title = _t('Transition');
        var pop = new instance.web.form.FormOpenPopup(self);
        pop.show_element(
            self.connector,
            parseInt(connector_id,10),      //FIXME Isn't connector_id supposed to be an int ?
            self.context || self.dataset.context,
            {
                title: _t("Open: ") + title
            }
        );
        pop.on_write.add(function() {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
        });
    },

    // Creates a popup to add a connector from node_source_id to node_dest_id.
    // dummy_cuteedge if not null, will be removed form the graph after the popup is closed.
    add_connector: function(node_source_id, node_dest_id, dummy_cuteedge){
        var self = this;
        var title = _t('Transition');
        var pop = new instance.web.form.SelectCreatePopup(self);

        pop.select_element(
            self.connector,
            {
                title: _t("Create:") + title,
                initial_view: 'form',
                disable_multiple_selection: true
            },
            this.dataset.domain,
            this.context || this.dataset.context
        );

        pop.on_select_elements.add_last(function(element_ids) {
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
        });
        // We want to destroy the dummy edge after a creation cancel. This destroys it even if we save the changes.
        // This is not a problem since the diagram is completely redrawn on saved changes.
        pop.$element.bind("dialogbeforeclose",function(){
            if(dummy_cuteedge){
                dummy_cuteedge.remove();
            }
        });

        var form_controller = pop.view_form;

        form_controller.on_record_loaded.add_last(function () {
            form_controller.fields[self.connectors.attrs.source].set_value(node_source_id);
            form_controller.fields[self.connectors.attrs.source].dirty = true;
            form_controller.fields[self.connectors.attrs.destination].set_value(node_dest_id);
            form_controller.fields[self.connectors.attrs.destination].dirty = true;
        });
    },

    on_pager_action: function(action) {
        switch (action) {
            case 'first':
                this.dataset.index = 0;
                break;
            case 'previous':
                this.dataset.previous();
                break;
            case 'next':
                this.dataset.next();
                break;
            case 'last':
                this.dataset.index = this.dataset.ids.length - 1;
                break;
        }
        var loaded = this.dataset.read_index(_.keys(this.fields_view.fields))
                .pipe(this.on_diagram_loaded);
        this.do_update_pager();
        return loaded;
    },

    do_update_pager: function(hide_index) {
        var $pager = this.$element.find('div.oe_diagram_pager');
        var index = hide_index ? '-' : this.dataset.index + 1;
        if(!this.dataset.count) {
            this.dataset.count = this.dataset.ids.length;
        }
        $pager.find('span.oe_pager_index').html(index);
        $pager.find('span.oe_pager_count').html(this.dataset.count);
    },

    do_show: function() {
        this.do_push_state({});
        return $.when(this._super(), this.on_pager_action('reload'));
    }
});
};

// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
<|endoftext|>


<commit_before>var get_ip = require('..')().get_ip,
    assert = require('assert'),
    request = {'headers': {'connection': {'remoteAddress': '172.0.0.1'}}};

describe('HTTP_X_FORWARDED_FOR Multiple IPs', function() {
  it('should return best matched proxy IP address first', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '192.168.255.182, 10.0.0.0, 127.0.0.1, 198.84.193.157, 177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '198.84.193.157');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Multiple IPs with Invalid IP Address', function() {
  it('should return best matched proxy IP address while handling an invalid address', function() {
    request.headers.HTTP_X_FORWARDED_FOR = 'unknown, 192.168.255.182, 10.0.0.0, 127.0.0.1, 198.84.193.157, 177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '198.84.193.157');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Single IP Address', function() {
  it('should return best matched proxy IP address if only one provided', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.139');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Single Private IP Address', function() {
  it('should return best matched public ip address if proxy returns a single private ip', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '192.168.255.182';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.132');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Malformed IP Address FallBack on HTTP_X_REAL_IP', function() {
  it('should return the next best match IP if proxy\'s ip is malformed', function() {
    request.headers.HTTP_X_FORWARDED_FOR = 'unknown 177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.132');
    assert.equal(request.clientIpRoutable, true);
  });
});

<commit_msg>more tests<commit_after>var get_ip = require('..')().get_ip,
    assert = require('assert'),
    request = {'headers': {'connection': {'remoteAddress': '172.0.0.1'}}};

describe('HTTP_X_FORWARDED_FOR Multiple IPs', function() {
  it('should return best matched proxy IP address first', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '192.168.255.182, 10.0.0.0, 127.0.0.1, 198.84.193.157, 177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '198.84.193.157');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Multiple IPs with Invalid IP Address', function() {
  it('should return best matched proxy IP address while handling an invalid address', function() {
    request.headers.HTTP_X_FORWARDED_FOR = 'unknown, 192.168.255.182, 10.0.0.0, 127.0.0.1, 198.84.193.157, 177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '198.84.193.157');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Single IP Address', function() {
  it('should return best matched proxy IP address if only one provided', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.139');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Single Private IP Address', function() {
  it('should return best matched public ip address if proxy returns a single private ip', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '192.168.255.182';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.132');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR Malformed IP Address FallBack on HTTP_X_REAL_IP', function() {
  it('should return the next best match IP if proxy\'s ip is malformed', function() {
    request.headers.HTTP_X_FORWARDED_FOR = 'unknown 177.139.233.139';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.132');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR NO IP Address FallBack on HTTP_X_REAL_IP', function() {
  it('should return the next best match IP if proxy returns no ip', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '';
    request.headers.HTTP_X_REAL_IP = '177.139.233.132';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.132');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR & HTTP_X_REAL_IP NO IP Address FallBack on REMOTE_ADDR', function() {
  it('should return the next best match IP if proxy and x_real_ip return no ip', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '';
    request.headers.HTTP_X_REAL_IP = '';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.133');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR NO IP Address FallBack on HTTP_X_REAL_IP', function() {
  it('should return the next best match IP if proxy returns no ip and x_real_ip is private', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '';
    request.headers.HTTP_X_REAL_IP = '192.168.255.182';
    request.headers.REMOTE_ADDR = '177.139.233.133';
    get_ip(request);
    assert.equal(request.clientIp, '177.139.233.133');
    assert.equal(request.clientIpRoutable, true);
  });
});

describe('HTTP_X_FORWARDED_FOR NO IP Address FallBack on HTTP_X_REAL_IP', function() {
  it('should return the next best match IP if proxy returns no ip and x_real_ip is private', function() {
    request.headers.HTTP_X_FORWARDED_FOR = '127.0.0.1';
    request.headers.HTTP_X_REAL_IP = '';
    request.headers.REMOTE_ADDR = '';
    get_ip(request);
    assert.equal(request.clientIp, '127.0.0.1');
    assert.equal(request.clientIpRoutable, false);
  });
});

<|endoftext|>