<commit_before>import Backbone from 'backbone';
import FrameView from './FrameView';
import { bindAll, isNumber, isNull, debounce } from 'underscore';
import { createEl, motionsEv } from 'utils/dom';
import Dragger from 'utils/Dragger';

export default Backbone.View.extend({
  events: {
    'click [data-action-remove]': 'remove',
    'mousedown [data-action-move]': 'startDrag'
  },

  initialize(opts = {}, conf = {}) {
    bindAll(
      this,
      'onScroll',
      'frameLoaded',
      'updateOffset',
      'remove',
      'startDrag'
    );
    const { model } = this;
    const config = {
      ...(opts.config || conf),
      frameWrapView: this
    };
    const { canvasView, em } = config;
    this.cv = canvasView;
    this.config = config;
    this.em = em;
    this.canvas = em && em.get('Canvas');
    this.ppfx = config.pStylePrefix || '';
    this.frame = new FrameView({ model, config });
    this.classAnim = `${this.ppfx}frame-wrapper--anim`;
    this.listenTo(model, 'loaded', this.frameLoaded);
    this.listenTo(model, 'change:x change:y', this.updatePos);
    this.listenTo(model, 'change:width change:height', this.updateSize);
    this.listenTo(model, 'destroy remove', this.remove);
    this.updatePos();
    this.setupDragger();
  },

  setupDragger() {
    const { canvas, model } = this;
    let dragX, dragY, zoom;
    const toggleEffects = on => {
      canvas.toggleFramesEvents(on);
    };

    this.dragger = new Dragger({
      onStart: () => {
        const { x, y } = model.attributes;
        zoom = this.em.getZoomMultiplier();
        dragX = x;
        dragY = y;
        toggleEffects();
      },
      onEnd: () => toggleEffects(1),
      setPosition: posOpts => {
        model.set({
          x: dragX + posOpts.x * zoom,
          y: dragY + posOpts.y * zoom
        });
      }
    });
  },

  startDrag(ev) {
    ev && this.dragger.start(ev);
  },

  remove(opts) {
    this.frame.remove(opts);
    Backbone.View.prototype.remove.apply(this, arguments);
    ['frame', 'dragger', 'cv', 'em', 'canvas', 'elTools'].forEach(
      i => (this[i] = 0)
    );
    return this;
  },

  updateOffset: debounce(function() {
    const { em, $el, frame } = this;
    if (!em) return;
    em.runDefault({ preserveSelected: 1 });
    $el.removeClass(this.classAnim);
    frame.model._emitUpdated();
  }),

  updatePos(md) {
    const { model, el } = this;
    const { x, y } = model.attributes;
    const { style } = el;
    this.frame.rect = 0;
    style.left = isNaN(x) ? x : `${x}px`;
    style.top = isNaN(y) ? y : `${y}px`;
    md && this.updateOffset();
  },

  updateSize: debounce(function() {
    this.updateDim();
  }),

  /**
   * Update dimensions of the frame
   * @private
   */
  updateDim() {
    const { em, el, $el, model, classAnim } = this;
    const { width, height } = model.attributes;
    const { style } = el;
    const currW = style.width || '';
    const currH = style.height || '';
    const newW = width || '';
    const newH = height || '';
    const noChanges = currW == newW && currH == newH;
    const un = 'px';
    this.frame.rect = 0;
    $el.addClass(classAnim);
    style.width = isNumber(newW) ? `${newW}${un}` : newW;
    style.height = isNumber(newH) ? `${newH}${un}` : newH;

    // Set width and height from DOM (should be done only once)
    if (isNull(width) || isNull(height)) {
      const newDims = {
        ...(!width ? { width: el.offsetWidth } : {}),
        ...(!height ? { height: el.offsetHeight } : {})
      };
      model.set(newDims, { silent: 1 });
    }

    // Prevent fixed highlighting box which appears when on
    // component hover during the animation
    em.stopDefault({ preserveSelected: 1 });
    noChanges ? this.updateOffset() : $el.one(motionsEv, this.updateOffset);
  },

  onScroll() {
    const { frame, em } = this;
    em.trigger('frame:scroll', {
      frame,
      body: frame.getBody(),
      target: frame.getWindow()
    });
  },

  frameLoaded() {
    const { frame } = this;
    frame.getWindow().onscroll = this.onScroll;
    this.updateDim();
  },

  render() {
    const { frame, $el, ppfx, cv, model, el } = this;
    const { onRender } = model.attributes;
    frame.render();
    $el
      .empty()
      .attr({ class: `${ppfx}frame-wrapper` })
      .append(
        `
      <div class="${ppfx}frame-wrapper__top gjs-two-color" data-frame-top>
        <div class="${ppfx}frame-wrapper__name" data-action-move>
          ${model.get('name') || ''}
        </div>
        <div class="${ppfx}frame-wrapper__top-r">
          <div class="${ppfx}frame-wrapper__icon" data-action-remove style="display: none">
            <svg viewBox="0 0 24 24"><path d="M19 4h-3.5l-1-1h-5l-1 1H5v2h14M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12z"></path></svg>
          </div>
        </div>
      </div>
      <div class="${ppfx}frame-wrapper__right" data-frame-right></div>
      <div class="${ppfx}frame-wrapper__left" data-frame-left></div>
      <div class="${ppfx}frame-wrapper__bottom" data-frame-bottom></div>
      `
      )<commit_msg>Set frame size on render<commit_after>import Backbone from 'backbone';
import FrameView from './FrameView';
import { bindAll, isNumber, isNull, debounce } from 'underscore';
import { createEl, motionsEv } from 'utils/dom';
import Dragger from 'utils/Dragger';

export default Backbone.View.extend({
  events: {
    'click [data-action-remove]': 'remove',
    'mousedown [data-action-move]': 'startDrag'
  },

  initialize(opts = {}, conf = {}) {
    bindAll(
      this,
      'onScroll',
      'frameLoaded',
      'updateOffset',
      'remove',
      'startDrag'
    );
    const { model } = this;
    const config = {
      ...(opts.config || conf),
      frameWrapView: this
    };
    const { canvasView, em } = config;
    this.cv = canvasView;
    this.config = config;
    this.em = em;
    this.canvas = em && em.get('Canvas');
    this.ppfx = config.pStylePrefix || '';
    this.frame = new FrameView({ model, config });
    this.classAnim = `${this.ppfx}frame-wrapper--anim`;
    this.listenTo(model, 'loaded', this.frameLoaded);
    this.listenTo(model, 'change:x change:y', this.updatePos);
    this.listenTo(model, 'change:width change:height', this.updateSize);
    this.listenTo(model, 'destroy remove', this.remove);
    this.updatePos();
    this.setupDragger();
  },

  setupDragger() {
    const { canvas, model } = this;
    let dragX, dragY, zoom;
    const toggleEffects = on => {
      canvas.toggleFramesEvents(on);
    };

    this.dragger = new Dragger({
      onStart: () => {
        const { x, y } = model.attributes;
        zoom = this.em.getZoomMultiplier();
        dragX = x;
        dragY = y;
        toggleEffects();
      },
      onEnd: () => toggleEffects(1),
      setPosition: posOpts => {
        model.set({
          x: dragX + posOpts.x * zoom,
          y: dragY + posOpts.y * zoom
        });
      }
    });
  },

  startDrag(ev) {
    ev && this.dragger.start(ev);
  },

  remove(opts) {
    this.frame.remove(opts);
    Backbone.View.prototype.remove.apply(this, arguments);
    ['frame', 'dragger', 'cv', 'em', 'canvas', 'elTools'].forEach(
      i => (this[i] = 0)
    );
    return this;
  },

  updateOffset: debounce(function() {
    const { em, $el, frame } = this;
    if (!em) return;
    em.runDefault({ preserveSelected: 1 });
    $el.removeClass(this.classAnim);
    frame.model._emitUpdated();
  }),

  updatePos(md) {
    const { model, el } = this;
    const { x, y } = model.attributes;
    const { style } = el;
    this.frame.rect = 0;
    style.left = isNaN(x) ? x : `${x}px`;
    style.top = isNaN(y) ? y : `${y}px`;
    md && this.updateOffset();
  },

  updateSize: debounce(function() {
    this.updateDim();
  }),

  /**
   * Update dimensions of the frame
   * @private
   */
  updateDim() {
    const { em, el, $el, model, classAnim } = this;
    this.frame.rect = 0;
    $el.addClass(classAnim);
    const { noChanges, width, height } = this.__handleSize();

    // Set width and height from DOM (should be done only once)
    if (isNull(width) || isNull(height)) {
      model.set(
        {
          ...(!width ? { width: el.offsetWidth } : {}),
          ...(!height ? { height: el.offsetHeight } : {})
        },
        { silent: 1 }
      );
    }

    // Prevent fixed highlighting box which appears when on
    // component hover during the animation
    em.stopDefault({ preserveSelected: 1 });
    noChanges ? this.updateOffset() : $el.one(motionsEv, this.updateOffset);
  },

  onScroll() {
    const { frame, em } = this;
    em.trigger('frame:scroll', {
      frame,
      body: frame.getBody(),
      target: frame.getWindow()
    });
  },

  frameLoaded() {
    const { frame } = this;
    frame.getWindow().onscroll = this.onScroll;
    this.updateDim();
  },

  __handleSize() {
    const un = 'px';
    const { model, el } = this;
    const { style } = el;
    const { width, height } = model.attributes;
    const currW = style.width || '';
    const currH = style.height || '';
    const newW = width || '';
    const newH = height || '';
    const noChanges = currW == newW && currH == newH;
    style.width = isNumber(newW) ? `${newW}${un}` : newW;
    style.height = isNumber(newH) ? `${newH}${un}` : newH;
    return { noChanges, width, height, newW, newH };
  },

  render() {
    const { frame, $el, ppfx, cv, model, el } = this;
    const { onRender } = model.attributes;
    this.__handleSize();
    frame.render();
    $el
      .empty()
      .attr({ class: `${ppfx}frame-wrapper` })
      .append(
        `
      <div class="${ppfx}frame-wrapper__top gjs-two-color" data-frame-top>
        <div class="${ppfx}frame-wrapper__name" data-action-move>
          ${model.get('name') || ''}
        </div>
        <div class="${ppfx}frame-wrapper__top-r">
          <div class="${ppfx}frame-wrapper__icon" data-action-remove style="display: none">
            <svg viewBox="0 0 24 24"><path d="M19 4h-3.5l-1-1h-5l-1 1H5v2h14M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12z"></path></svg>
          </div>
        </div>
      </div>
      <div class="${ppfx}frame-wrapper__right" data-frame-right></div>
      <div class="${ppfx}frame-wrapper__left" data-frame-left></div>
      <div class="${ppfx}frame-wrapper__bottom" data-frame-bottom></div>
      `
      )
{'fraction_non_alphanumeric': 0.17269115224343445, 'fraction_numerical': 0.009497044287237135, 'mean_word_length': 2.475917817446952, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4989777', 'n_tokens_mistral': 3534, 'n_tokens_neox': 3481, 'n_words': 761}