Показать сообщение отдельно
  #4 (permalink)  
Старый 03.09.2013, 10:35
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от monolithed
Разметка для Google closure compiler
боролся я как то с этим, хотя мне больше волновал вопрос с автокомплитом. В итоге вышло примерно так, GCC при этом не плачет и автокомплит работает хорошо:
/**
 * Component является общим предком всех классов компонентов.
 *
 * @author <a href="mailto:spb.piksel@gmail.com">Dmitrii Pakhtinov</a>
 * @requires Class
 * @version 1.0 - 12/20/2012
 */
Class("SP.Component", function() {
  /**
   * Ссылка на родительский компонент
   *
   * @type {SP.Component|null}
   * @private
   */
  var owner = null;
  /**
   * Список дочерних компонентов
   *
   * @type {Array}
   * @private
   */
  var components = [];
  /**
   * @class SP.Component
   */
  return {
    /**
     * Общий предок всех компонентов, каждый компонент обязан наследоватся от этого класса
     *
     * @namespace SP
     * @constructs
     * @constructor
     */
    Component: function() {
        // dummy
    },
    /**
     * Устанавливает или возвращает родительский компонент
     * Для удаления родительского компонента установите значение <b>null</b>
     *
     * Родительский компонент является владельцем компонента и может оперировать
     * свойствами дочернего компонента. Присвоеный компонент является владельцем
     * компонента которому его присвоили и в случае удаления владельца, будут
     * удалены все его подчиненные компоненты, если вы не хотите потерять подчиненные
     * копоненты, позаботьтесь об этом заранее
     *
     * @type {SP.Component|null}
     * @property
     * @public
     * @final
     */
    owner: {
      /**
       * @param {SP.Component|null} component
       */
      set: function(component) {

        // пропускаем только если текущая ссылка на владельца иная и это наследник компонента
        if (component !== owner && (component === null || Class.instanceOf(component, this.__class__))) {

          // удаляем у текущего владельца данный компонент
          if (owner) {
            // если владелец не позволит удалить компонет
            if (owner.onremovecomponent(this) === false) {
              return;
            }
            owner.removeComponent.call(false, this, owner);
          }

          // добавляем владельцу текущий компонент
          if (component) {
            // если компонент не позволит его добавить
            if (component.oninsertcomponent(this) === false) {
              return;
            }
            component.insertComponent.call(false, this, component);
          }

          // меняем ссылку на владельца
          owner = component;
        }
      },

      get: function() {
        return owner;
      }
    },

    /**
     * Добавляет в список дочерний компонент
     *
     * @param {SP.Component} component компонент который будет дочерним
     * @return {Boolean} возвращает <b>true</b> при успешном выполнении, в противном случае <b>false</b>
     * @public
     * @final
     * @see {@link get.components}
     */
    insertComponent: function(component) {

      // Условие для внутреннего использования
      if (this instanceof Boolean && arguments.length > 1) {

        // Добавляем компонент в список
        components[components.length] = component;

        // информируем компонент о том что его добавли владельцу
        component.oninsert(arguments[1]);

      } else if (Class.instanceOf(component, this.__class__)) {
        // Если объект является компонентом пробуем добавить его
        return components.length < (component.owner = this, components.length);
      }

      return false;
    },

    /**
     * Удаляет из списка дочерний компонент
     *
     * @param {SP.Component} component компонент который является дочерним этого компонента
     * @return {Boolean} возвращает <b>true</b> при успешном выполнении, в противном случае <b>false</b>
     * @public
     * @final
     * @see {@link get.components}
     */
    removeComponent: function(component) {

      // Условие для внутреннего использования
      if (this instanceof Boolean && arguments.length > 1) {

        var index = -1;

        if ("indexOf" in components) {
          // новая версия ECMAScript имеет поддержку метода indexOf для массивов
          index = components.indexOf(component);
        } else {
          // для более старой версии ECMAScript
          for(var i = components.length; i--;) {
            if (components[i] === component) {
              index = i;
              break;
            }
          }
        }

        if (index >= 0) {

          // удаляем компонент из стека
          components.splice(index, 1);

          // информируем компонент о том что его удалили из родительского компонента
          component.onremove(arguments[1]);
        }

      } else if (Class.instanceOf(component, this.__class__)) {
        // Если объект является компонентом удаляем у него родителя
        return components.length > (component.owner = null, components.length);
      }

      return false;
    },

    /**
     * Содержит список всех дочерних компонентов
     *
     * @type {Array}
     * @property
     * @public
     * @see {@link insertComponent}
     * @see {@link removeComponent}
     */
    components: {
      get:function() {
        // не будем возвращать ссылку на оригинальный список компонентов, отдаем копию
        return components.slice(0);
      }
    },

    /**
     * Устанавливает или возвращает позицию компонента
     *
     * Если параметр component не задан, то в случае если задан position установит
     * текущий компонент у его владельца на новую позицию, если же параметр position
     * так же не задан, то вернет текущую позицию у владельца.
     *
     * Если компонент не имеет владельца, вернет значение -1
     *
     * @param {SP.Component} [component]
     * @param {Integer} [position]
     * @return {Integer}
     * @public
     */
    componentPosition: function(component, position) {

      // ищем компонент у владельца
      if (typeof component === "number" || !component) {
        return owner ? owner.componentPosition(this, component) : -1;
      }

      var index = -1, length = components.length;

      if ("indexOf" in components) {
        // новая версия ECMAScript имеет поддержку метода indexOf для массивов
        index = components.indexOf(component);
      } else {
        // для более старой версии ECMAScript
        for(var i = components.length; i--;) {
          if (components[i] === component) {
            index = i;
            break;
          }
        }
      }

      // если позиция или компонент не определены, возвращаем текущуюю позицию
      if (typeof position !== "number" || index < 0) {
        return index;
      }

      // попытаемся нормализовать позицию
      while(position < 0 || position >= length) {
        position = position < 0 ? length + position : position >= length ? position - length : position;
      }

      // если текущая позиция не равна новой позиции
      if (index !== position) {

        // удаляем компонент из текущей позиции
        components.splice(index, 1);

        if (position === 0) {
          // вставляем в начало
          components.unshift(component);
        } else if (position === components.length) {
          // вставляем в конец
          components.push(component);
        } else {
          // вставляем где то в середине
          components = components.slice(0, position).concat(component, components.slice(position));
        }

        length = index < position ? position : index;
        index = index < position ? index : position;

        for( ; index <= length; index++ ) {
          components[index].onchangeposition(index);
        }
      }

      // возвращаем позицию компонента
      return position;
    },

    /**
     * Событие страбатывает у владельца в случае если добавляют в него новый компонент
     * Верните <b>false</b> если не хотите что бы в ваш компонент что-то добавляли.
     *
     * @protected
     * @param {SP.Component} component
     */
    oninsertcomponent: function(component) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает у владельца при удалении из него компонента
     * Верните <b>false</b> если не хотите что бы из владельца что-то удаляли
     *
     * @protected
     * @param {SP.Component} component
     */
    onremovecomponent: function(component) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает у компонента в том случае если он был успешно принят владельцем
     *
     * @protected
     * @param {SP.Component} owner
     */
    oninsert: function(owner) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает если компонент успешно был удален владельцем
     *
     * @protected
     * @param {SP.Component} owner
     */
    onremove: function(owner) {
      /* virtual protected */
    },

    /**
     * Событие срабатывает если сменили позицию компонента
     *
     * @protected
     * @param {Integer} position
     */
    onchangeposition: function(position) {
      /* virtual protected */
    }
  }
});
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием