<commit_before>/*global nameSpaceName:true, jQuery: true, window: true */
(function (nameSpaceName, domVendor) {

    /**
     *    The nameSpaceName  NameSpace, an IIFE
     *    @namespace
     *    @export
     *    @return {window.nameSpaceName}
     */
    Object.defineProperty(window, nameSpaceName, {
        value: (function () {
            ///(IIFE) Intializes the nameSpaceName namespace.
            ///<returns type="window.nameSpaceName">The nameSpaceName namespace.</returns>

            var nsInternal = {
                dependents: []
            };

            Object.defineProperty(nsInternal, 'getNsMembers', {
                value: function () {
                    var members = [];

                    function recurseTree(key, lastKey) {
                        if (typeof (key) === 'string') {
                            members.push(lastKey + '.' + key);
                        }
                        if (domVendor.isPlainObject(key)) {
                            Object.keys(key).forEach(function (k) {
                                if (typeof (k) === 'string') {
                                    members.push(lastKey + '.' + k);
                                }
                                if (domVendor.isPlainObject(key[k])) {
                                    recurseTree(key[k], lastKey + '.' + k);
                                }
                            });
                        }
                    }
                    if (typeof NsTree != "undefined") {
                        Object.keys(NsTree[nameSpaceName]).forEach(function (key) {
                            if (domVendor.isPlainObject(NsTree[nameSpaceName][key])) {
                                recurseTree(NsTree[nameSpaceName][key], nameSpaceName);
                            }
                        });
                    }
                    return members;
                }
            });

            Object.defineProperty(nsInternal, 'alertDependents', {
                value: function (imports) {
                    var deps = nsInternal.dependents.filter(function (depOn) {
                        return false === depOn(imports);
                    });
                    if (Array.isArray(deps)) {
                        nsInternal.dependents = deps;
                    }
                }
            });

            /**
             *    Internal nameSpaceName method to create new "sub" namespaces on arbitrary child objects.
             *	@param spacename {String} the namespace name
             */
            function makeNameSpace(spacename) {
                /// Internal nameSpaceName method to create new "sub" namespaces on arbitrary child objects.
                /// <param name="proto" type="Object"> String to parse </param>
                /// <returns type="Object">The new child namespace.</returns>
                var Class = new Function(
                    "return function " + spacename + "(){}"
                )();
                function Base(nsName) {
                    var proto = this;
                    Object.defineProperty(this, 'lift', {
                        value:
                            /**
                             *	"Lift" an Object into the prototype of the namespace.
                             *	This Object will be readable/executable but is otherwise immutable.
                             *   @param {String} name The name of the object to lift
                             *   @param {Object} obj Any, arbitrary Object to use as the value.
                             *   @return {Object} The value of the new property.
                             */
                            function (name, obj, enumerable) {
                                'use strict';
                                /// "Lift" an Object into the prototype of the namespace. This Object will be readable/executable but is otherwise immutable.
                                /// <param name="name" type="String">The name of the object to lift.</param>
                                /// <param name="obj" type="Object">Any, arbitrary Object to use as the value.</param>
                                /// <returns type="Object">The value of the new property.</returns>
                                if (!(typeof name === 'string') || name === '') {
                                    throw new Error('Cannot lift a new property without a valid name.');
                                }
                                if (!obj) {
                                    throw new Error('Cannot lift a new property without a valid property instance.');
                                }
                                    Object.defineProperty(proto, name, {
                                        value: obj,
                                        enumerable: false !== enumerable
                                    });
                                    nsInternal.alertDependents(nsName + '.' + spacename + '.' + name);

                                return obj;
                            }
                    });

                    proto.lift('makeSubNameSpace',
                        /**
                         *	Create a new, static namespace on the current parent (e.g. nsName.to... || nsName.is...)
                         *   @param {String} subNameSpace The name of the new namespace.
                         *   @return {Object} The new namespace.
                         */
                        function (subNameSpace) {
                            'use strict';
                            /// Create a new, static namespace on the current parent (e.g. nsName.to... || nsName.is...).
                            /// <param name="subNameSpace" type="String">The name of the new namespace.</param>
                            /// <returns type="Object">The new namespace.</returns>
                            if (!(typeof subNameSpace === 'string') || subNameSpace === '') {
                                throw new Error('Cannot create a new sub namespace without a valid name.');
                            }
                            nsInternal.alertDependents(nsName + '.' + subNameSpace);

                            var newNameSpace = makeNameSpace(subNameSpace);

                            newNameSpace.lift('constants', makeNameSpace('constants'));

                            proto.lift(subNameSpace, newNameSpace);
                            return newNameSpace;
                        }, false);
                }

                Class.prototype = new Base(spacename);
                //Class.prototype.parent = Base.prototype;

                return new Class(spacename);
            };

            var NsOut = makeNameSpace(nameSpaceName);

            NsOut.lift('constants', makeNameSpace('constants'));

            NsOut.lift('?', domVendor);

            /**
             *    "Depend" an Object upon another member of this namespace, upon another namespace,
             *   or upon a member of another namespace
             *   @param (Array) array of dependencies for this method
             *   @param (Function) obj Any, arbitrary Object to use as the value
             */
            function dependsOn(dependencies, callBack, imports) {
                'use strict';
                var ret = false;
                var nsMembers = nsInternal.getNsMembers();
                if (dependencies && dependencies.length > 0 && callBack) {
                    var missing = dependencies.filter(function (depen) {
                        return (nsMembers.indexOf(depen) === -1 && (!imports || imports !== depen));
                    });
                    if (missing.length === 0) {
                        ret = true;
                        callBack();
                    }
                    else {
                        nsInternal.dependents.push(function (imports) {
                            return dependsOn(missing, callBack, imports);
                        });
                    }
                }
                return ret;
            };
            NsOut.lift('dependsOn', dependsOn, false);

            return NsOut;

        }())
    });

}('OJ', jQuery));
<commit_msg>Manually merging more fixes back into OJ base.<commit_after>/*global nameSpaceName:true, jQuery: true, window: true */
(function (nameSpaceName, domVendor) {

    //Define a quick and dirty way to get the 'instanceof' value of an object.
    //CAUTION: this is the Object prototype. Possible collisions abound.
    Object.defineProperties(Object.prototype, {
        getInstanceName: {
            value:
                /**
                 * Get the name of the instance of this object
                */
                function () {
                    var funcNameRegex = /function (.{1,})\(/;
                    var results = (funcNameRegex).exec((this).constructor.toString());
                    return (results && results.length > 1) ? results[1] : "";
                }
        }
    });

    /**
     * An internal representation of the namespace tree
     * @internal
    */
    var NsTree = {};

    /**
     *    The nameSpaceName  NameSpace, an IIFE
     *    @namespace
     *    @export
     *    @global */ +nameSpaceName + /*
     *    @return {window.nameSpaceName}
     */
    Object.defineProperty(window, nameSpaceName, {
        value:
            /**
             * Intializes the nameSpaceName namespace.
             * @return {window.nameSpaceName}
            */
            (function () {

                var nsInternal = {
                    dependents: []
                };

                Object.defineProperty(nsInternal, 'getNsMembers', {
                    value:
                        /**
                         * Fetches the registered properties and methods on the namespace and its child namespaces
                         * @interal
                         * @return {Array} An array of members defined as strings (e.g. 'namespace.constants.astringcnst')
                        */
                        function () {
                            var members = [];

                            function recurseTree(key, lastKey) {
                                if (typeof (key) === 'string') {
                                    members.push(lastKey + '.' + key);
                                }
                                if (domVendor.isPlainObject(key)) {
                                    Object.keys(key).forEach(function (k) {
                                        if (typeof (k) === 'string') {
                                            members.push(lastKey + '.' + k);
                                        }
                                        if (domVendor.isPlainObject(key[k])) {
                                            recurseTree(key[k], lastKey + '.' + k);
                                        }
                                    });
                                }
                            }
                            Object.keys(NsTree[nameSpaceName]).forEach(function (key) {
                                if (domVendor.isPlainObject(NsTree[nameSpaceName][key])) {
                                    recurseTree(NsTree[nameSpaceName][key], nameSpaceName);
                                }
                            });
                            return members;
                        }
                });

                Object.defineProperty(nsInternal, 'alertDependents', {
                    value:
                        /**
                         * To support dependency management, when a property is lifted onto the namespace, notify dependents to initialize
                         * @internal
                        */
                        function (imports) {
                        var deps = nsInternal.dependents.filter(function (depOn) {
                            return false === depOn(imports);
                        });
                        if (Array.isArray(deps)) {
                            nsInternal.dependents = deps;
                        }
                    }
                });

                /**
                 * Internal nameSpaceName method to create new "sub" namespaces on arbitrary child objects.
                 * @internal
                 * @param spacename {String} the namespace name
                 * @param tree {Object} the internal tree representation of the current level of the namespace
                 * @return namespace {Object} A new namespace
                 */
                function makeNameSpace(spacename, tree) {
                    /**
                     * An internal mechanism to represent the instance of this namespace
                     * @constructor
                    */
                    var Class = new Function(
                        "return function " + spacename + "(){}"
                    )();

                    /**
                     * The derived instance to be constructed
                     * @constructor
                    */
                    function Base(nsName) {
                        var proto = this;
                        tree[nsName] = tree[nsName] || {};
                        var nsTree = tree[nsName];

                        Object.defineProperty(this, 'lift', {
                            value:
                                /**
                                 *  "Lift" an Object into the prototype of the namespace.
                                 *  This Object will be readable/executable but is otherwise immutable.
                                 *   @param {String} name The name of the object to lift
                                 *   @param {Object} obj Any, arbitrary Object to use as the value.
                                 *   @return {Object} The value of the new property.
                                 */
                                function (name, obj, enumerable) {
                                    'use strict';
                                    if (!(typeof name === 'string') || name === '') {
                                        throw new Error('Cannot lift a new property without a valid name.');
                                    }
                                    if (!obj) {
                                        throw new Error('Cannot lift a new property without a valid property instance.');
                                    }

                                    //Guard against obliterating the tree as the tree is recursively extended
                                    nsTree[name] = nsTree[name] || {
                                        name: name,
                                        type: typeof obj,
                                        instance: obj.getInstanceName ? obj.getInstanceName() : 'unknown'
                                    };

                                    Object.defineProperty(proto, name, {
                                        value: obj,
                                        enumerable: false !== enumerable
                                    });
                                    nsInternal.alertDependents(nsName + '.' + spacename + '.' + name);

                                    return obj;
                                }
                        });

                        proto.lift('makeSubNameSpace',
                            /**
                             *  Create a new, static namespace on the current parent (e.g. nsName.to... || nsName.is...)
                             *   @param {String} subNameSpace The name of the new namespace.
                             *   @return {Object} The new namespace.
                             */
                            function (subNameSpace) {
                                'use strict';
                                if (!(typeof subNameSpace === 'string') || subNameSpace === '') {
                                    throw new Error('Cannot create a new sub namespace without a valid name.');
                                }
                                nsInternal.alertDependents(nsName + '.' + subNameSpace);

                                var newNameSpace = makeNameSpace(subNameSpace, nsTree);

                                if (subNameSpace !== 'constants') {
                                    newNameSpace.lift('constants', makeNameSpace('constants', nsTree), false);
                                }

                                proto.lift(subNameSpace, newNameSpace, false);
                                return newNameSpace;
                            }, false);
                    }

                    Class.prototype = new Base(spacename);
                    //Class.prototype.parent = Base.prototype;

                    return new Class(spacename);
                };

                //Create the root of the tree as the current namespace
                NsTree[nameSpaceName] = {};

                //Define the core namespace and the return of this class
                var NsOut = makeNameSpace(nameSpaceName, NsTree[nameSpaceName]);

                //Cache a handle on the vendor (probably jQuery) on the root namespace
                NsOut.lift('?', domVendor, false);

                //Cache the tree (useful for documentation/visualization/debugging)
                NsOut.lift('tree', NsTree[nameSpaceName], false);

                /**
                 *    "Depend" an Object upon another member of this namespace, upon another namespace,
                 *   or upon a member of another namespace
                 *   @param (Array) array of dependencies for this method
                 *   @param (Function) obj Any, arbitrary Object to use as the value
                 */
                function dependsOn(dependencies, callBack, imports) {
                    'use strict';
                    var ret = false;
                    var nsMembers = nsInternal.getNsMembers();
                    if (dependencies && dependencies.length > 0 && callBack) {
                        var missing = dependencies.filter(function (depen) {
                            return (nsMembers.indexOf(depen) === -1 && (!imports || imports !== depen));
                        });
                        if (missing.length === 0) {
                            ret = true;
                            callBack();
                        }
                        else {
                            nsInternal.dependents.push(function (imports) {
                                return dependsOn(missing, callBack, imports);
                            });
                        }
                    }
                    return ret;
                };
                NsOut.lift('dependsOn', dependsOn, false);

                return NsOut;

            }())
    });

}('OJ', jQuery));
<|endoftext|>


<commit_before>/**
 * --------------------------------------------
 * AdminLTE IFrame.js
 * License MIT
 * --------------------------------------------
 */

import $ from 'jquery'

/**
 * Constants
 * ====================================================
 */

const NAME = 'IFrame'
const DATA_KEY = 'lte.iframe'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_DATA_TOGGLE = '[data-widget="iframe"]'
const SELECTOR_DATA_TOGGLE_CLOSE = '[data-widget="iframe-close"]'
const SELECTOR_DATA_TOGGLE_SCROLL_LEFT = '[data-widget="iframe-scrollleft"]'
const SELECTOR_DATA_TOGGLE_SCROLL_RIGHT = '[data-widget="iframe-scrollright"]'
const SELECTOR_DATA_TOGGLE_FULLSCREEN = '[data-widget="iframe-fullscreen"]'
const SELECTOR_CONTENT_WRAPPER = '.content-wrapper'
const SELECTOR_CONTENT_IFRAME = `${SELECTOR_CONTENT_WRAPPER} iframe`
const SELECTOR_TAB_NAV = `${SELECTOR_CONTENT_WRAPPER}.iframe-mode .nav`
const SELECTOR_TAB_NAVBAR_NAV = `${SELECTOR_CONTENT_WRAPPER}.iframe-mode .navbar-nav`
const SELECTOR_TAB_NAVBAR_NAV_ITEM = `${SELECTOR_TAB_NAVBAR_NAV} .nav-item`
const SELECTOR_TAB_NAVBAR_NAV_LINK = `${SELECTOR_TAB_NAVBAR_NAV} .nav-link`
const SELECTOR_TAB_CONTENT = `${SELECTOR_CONTENT_WRAPPER}.iframe-mode .tab-content`
const SELECTOR_TAB_EMPTY = `${SELECTOR_TAB_CONTENT} .tab-empty`
const SELECTOR_TAB_LOADING = `${SELECTOR_TAB_CONTENT} .tab-loading`
const SELECTOR_TAB_PANE = `${SELECTOR_TAB_CONTENT} .tab-pane`
const SELECTOR_SIDEBAR_MENU_ITEM = '.main-sidebar .nav-item > a.nav-link'
const SELECTOR_SIDEBAR_SEARCH_ITEM = '.sidebar-search-results .list-group-item'
const SELECTOR_HEADER_MENU_ITEM = '.main-header .nav-item a.nav-link'
const SELECTOR_HEADER_DROPDOWN_ITEM = '.main-header a.dropdown-item'
const CLASS_NAME_IFRAME_MODE = 'iframe-mode'
const CLASS_NAME_FULLSCREEN_MODE = 'iframe-mode-fullscreen'

const Default = {
  onTabClick(item) {
    return item
  },
  onTabChanged(item) {
    return item
  },
  onTabCreated(item) {
    return item
  },
  autoIframeMode: true,
  autoItemActive: true,
  autoShowNewTab: true,
  autoDarkMode: false,
  allowDuplicates: false,
  loadingScreen: true,
  useNavbarItems: true,
  scrollOffset: 40,
  scrollBehaviorSwap: false,
  iconMaximize: 'fa-expand',
  iconMinimize: 'fa-compress'
}

/**
 * Class Definition
 * ====================================================
 */

class IFrame {
  constructor(element, config) {
    this._config = config
    this._element = element
    this._init()
  }

  // Public

  onTabClick(item) {
    this._config.onTabClick(item)
  }

  onTabChanged(item) {
    this._config.onTabChanged(item)
  }

  onTabCreated(item) {
    this._config.onTabCreated(item)
  }

  createTab(title, link, uniqueName, autoOpen) {
    let tabId = `panel-${uniqueName}`
    let navId = `tab-${uniqueName}`

    if (this._config.allowDuplicates) {
      tabId += `-${Math.floor(Math.random() * 1000)}`
      navId += `-${Math.floor(Math.random() * 1000)}`
    }

    const newNavItem = `
${title}
`
    $(SELECTOR_TAB_NAVBAR_NAV).append(unescape(escape(newNavItem)))

    const newTabItem = `<div class="tab-pane fade" id="${tabId}" role="tabpanel" aria-labelledby="${navId}"><iframe src="${link}"></iframe></div>`
    $(SELECTOR_TAB_CONTENT).append(unescape(escape(newTabItem)))

    if (autoOpen) {
      if (this._config.loadingScreen) {
        const $loadingScreen = $(SELECTOR_TAB_LOADING)
        $loadingScreen.fadeIn()
        $(`${tabId} iframe`).ready(() => {
          if (typeof this._config.loadingScreen === 'number') {
            this.switchTab(`#${navId}`)
            setTimeout(() => {
              $loadingScreen.fadeOut()
            }, this._config.loadingScreen)
          } else {
            this.switchTab(`#${navId}`)
            $loadingScreen.fadeOut()
          }
        })
      } else {
        this.switchTab(`#${navId}`)
      }
    }

    this.onTabCreated($(`#${navId}`))
  }

  openTabSidebar(item, autoOpen = this._config.autoShowNewTab) {
    let $item = $(item).clone()
    if ($item.attr('href') === undefined) {
      $item = $(item).parent('a').clone()
    }

    $item.find('.right, .search-path').remove()
    let title = $item.find('p').text()
    if (title === '') {
      title = $item.text()
    }

    const link = $item.attr('href')
    if (link === '#' || link === '' || link === undefined) {
      return
    }

    const uniqueName = link.replace('./', '').replace(/["#&'./:=?[\]]/gi, '-').replace(/(--)/gi, '')
    const navId = `tab-${uniqueName}`

    if (!this._config.allowDuplicates && $(`#${navId}`).length > 0) {
      return this.switchTab(`#${navId}`)
    }

    if ((!this._config.allowDuplicates && $(`#${navId}`).length === 0) || this._config.allowDuplicates) {
      this.createTab(title, link, uniqueName, autoOpen)
    }
  }

  switchTab(item) {
    const $item = $(item)
    const tabId = $item.attr('href')

    $(SELECTOR_TAB_EMPTY).hide()
    $(`${SELECTOR_TAB_NAVBAR_NAV} .active`).tab('dispose').removeClass('active')
    this._fixHeight()

    $item.tab('show')
    $item.parents('li').addClass('active')
    this.onTabChanged($item)

    if (this._config.autoItemActive) {
      this._setItemActive($(`${tabId} iframe`).attr('src'))
    }
  }

  removeActiveTab(type, element) {
    if (type == 'all') {
      $(SELECTOR_TAB_NAVBAR_NAV_ITEM).remove()
      $(SELECTOR_TAB_PANE).remove()
      $(SELECTOR_TAB_EMPTY).show()
    } else if (type == 'all-other') {
      $(`${SELECTOR_TAB_NAVBAR_NAV_ITEM}:not(.active)`).remove()
      $(`${SELECTOR_TAB_PANE}:not(.active)`).remove()
    } else if (type == 'only-this') {
      const $navClose = $(element)
      const $navItem = $navClose.parent('.nav-item')
      const $navItemParent = $navItem.parent()
      const navItemIndex = $navItem.index()
      const tabId = $navClose.siblings('.nav-link').attr('aria-controls')
      $navItem.remove()
      $(`#${tabId}`).remove()
      if ($(SELECTOR_TAB_CONTENT).children().length == $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).length) {
        $(SELECTOR_TAB_EMPTY).show()
      } else {
        const prevNavItemIndex = navItemIndex - 1
        this.switchTab($navItemParent.children().eq(prevNavItemIndex).find('a.nav-link'))
      }
    } else {
      const $navItem = $(`${SELECTOR_TAB_NAVBAR_NAV_ITEM}.active`)
      const $navItemParent = $navItem.parent()
      const navItemIndex = $navItem.index()
      $navItem.remove()
      $(`${SELECTOR_TAB_PANE}.active`).remove()
      if ($(SELECTOR_TAB_CONTENT).children().length == $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).length) {
        $(SELECTOR_TAB_EMPTY).show()
      } else {
        const prevNavItemIndex = navItemIndex - 1
        this.switchTab($navItemParent.children().eq(prevNavItemIndex).find('a.nav-link'))
      }
    }
  }

  toggleFullscreen() {
    if ($('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) {
      $(`${SELECTOR_DATA_TOGGLE_FULLSCREEN} i`).removeClass(this._config.iconMinimize).addClass(this._config.iconMaximize)
      $('body').removeClass(CLASS_NAME_FULLSCREEN_MODE)
      $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).height('100%')
      $(SELECTOR_CONTENT_WRAPPER).height('100%')
      $(SELECTOR_CONTENT_IFRAME).height('100%')
    } else {
      $(`${SELECTOR_DATA_TOGGLE_FULLSCREEN} i`).removeClass(this._config.iconMaximize).addClass(this._config.iconMinimize)
      $('body').addClass(CLASS_NAME_FULLSCREEN_MODE)
    }

    $(window).trigger('resize')
    this._fixHeight(true)
  }

  // Private

  _init() {
    const usingDefTab = ($(SELECTOR_TAB_CONTENT).children().length > 2)

    if (usingDefTab) {
      const $el = $(`${SELECTOR_TAB_PANE}:first-child`)
      $el.show()
      this._setItemActive($el.find('iframe').attr('src'))
    }

    this._setupListeners()
    this._fixHeight(!usingDefTab)
  }

  _initFrameElement() {
    if (window.frameElement && this._config.autoIframeMode) {
      const $body = $('body')
      $body.addClass(CLASS_NAME_IFRAME_MODE)

      if (this._config.autoDarkMode) {
        $body.addClass('dark-mode')
      }
    }
  }

  _navScroll(offset) {
    const leftPos = $(SELECTOR_TAB_NAVBAR_NAV).scrollLeft()
    $(SELECTOR_TAB_NAVBAR_NAV).animate({ scrollLeft: (leftPos + offset) }, 250, 'linear')
  }

  _setupListeners() {
    $(window).on('resize', () => {
      setTimeout(() => {
        this._fixHeight()
      }, 1)
    })
    if ($(SELECTOR_CONTENT_WRAPPER).hasClass(CLASS_NAME_IFRAME_MODE)) {
      $(document).on('click', `${SELECTOR_SIDEBAR_MENU_ITEM}, ${SELECTOR_SIDEBAR_SEARCH_ITEM}`, e => {
        e.preventDefault()
        this.openTabSidebar(e.target)
      })
      if (this._config.useNavbarItems) {
        $(document).on('click', `${SELECTOR_HEADER_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`, e => {
          e.preventDefault()
          this.openTabSidebar(e.target)
        })
      }
    }

    $(document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, e => {
      e.preventDefault()
      this.onTabClick(e.target)
      this.switchTab(e.target)
    })
    $(document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, e => {
      e.preventDefault()
      this.onTabClick(e.target)
      this.switchTab(e.target)
    })
    $(document).on('click', SELECTOR_DATA_TOGGLE_CLOSE, e => {
      e.preventDefault()
      let { target } = e

      if (target.nodeName == 'I') {
        target = e.target.offsetParent
      }

      this.removeActiveTab(target.attributes['data-type'] ? target.attributes['data-type'].nodeValue : null, target)
    })
    $(document).on('click', SELECTOR_DATA_TOGGLE_FULLSCREEN, e => {
      e.preventDefault()
      this.toggleFullscreen()
    })
    let mousedown = false
    let mousedownInterval = null
    $(document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_LEFT, e => {
      e.preventDefault()
      clearInterval(mousedownInterval)

      let { scrollOffset } = this._config

      if (!this._config.scrollBehaviorSwap) {
        scrollOffset = -scrollOffset
      }

      mousedown = true
      this._navScroll(scrollOffset)

      mousedownInterval = setInterval(() => {
        this._navScroll(scrollOffset)
      }, 250)
    })
    $(document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_RIGHT, e => {
      e.preventDefault()
      clearInterval(mousedownInterval)

      let { scrollOffset } = this._config

      if (this._config.scrollBehaviorSwap) {
        scrollOffset = -scrollOffset
      }

      mousedown = true
      this._navScroll(scrollOffset)

      mousedownInterval = setInterval(() => {
        this._navScroll(scrollOffset)
      }, 250)
    })
    $(document).on('mouseup', () => {
      if (mousedown) {
        mousedown = false
        clearInterval(mousedownInterval)
        mousedownInterval = null
      }
    })
  }

  _setItemActive(href) {
    $(`${SELECTOR_SIDEBAR_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`).removeClass('active')
    $(SELECTOR_HEADER_MENU_ITEM).parent().removeClass('active')

    const $headerMenuItem = $(`${SELECTOR_HEADER_MENU_ITEM}[href$="${href}"]`)
    const $headerDropdownItem = $(`${SELECTOR_HEADER_DROPDOWN_ITEM}[href$="${href}"]`)
    const $sidebarMenuItem = $(`${SELECTOR_SIDEBAR_MENU_ITEM}[href$="${href}"]`)

    $headerMenuItem.each((i, e) => {
      $(e).parent().addClass('active')
    })
    $headerDropdownItem.each((i, e) => {
      $(e).addClass('active')
    })
    $sidebarMenuItem.each((i, e) => {
      $(e).addClass('active')
      $(e).parents('.nav-treeview').prevAll('.nav-link').addClass('active')
    })
  }

  _fixHeight(tabEmpty = false) {
    if ($('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) {
      const windowHeight = $(window).height()
      const navbarHeight = $(SELECTOR_TAB_NAV).outerHeight()
      $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}, ${SELECTOR_CONTENT_IFRAME}`).height(windowHeight - navbarHeight)
      $(SELECTOR_CONTENT_WRAPPER).height(windowHeight)
    } else {
      const contentWrapperHeight = parseFloat($(SELECTOR_CONTENT_WRAPPER).css('height'))
      const navbarHeight = $(SELECTOR_TAB_NAV).outerHeight()
      if (tabEmpty == true) {
        setTimeout(() => {
          $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).height(contentWrapperHeight - navbarHeight)
        }, 50)
      } else {
        $(SELECTOR_CONTENT_IFRAME).height(contentWrapperHeight - navbarHeight)
      }
    }
  }

  // Static

  static _jQueryInterface(config) {
    if ($(SELECTOR_DATA_TOGGLE).length > 0) {
      let data = $(this).data(DATA_KEY)

      if (!data) {
        data = $(this).data()
      }

      const _options = $.extend({}, Default, typeof config === 'object' ? config : data)
      localStorage.setItem('AdminLTE:IFrame:Options', JSON.stringify(_options))

      const plugin = new IFrame($(this), _options)

      $(this).data(DATA_KEY, typeof config === 'object' ? config : data)

      if (typeof config === 'string' && /createTab|openTabSidebar|switchTab|removeActiveTab/.test(config)) {
        plugin[config]()
      }
    } else {
      new IFrame($(this), JSON.parse(localStorage.getItem('AdminLTE:IFrame:Options')))._initFrameElement()
    }
  }
}

/**
 * Data API
 * ====================================================
 */

$(window).on('load', () => {
  IFrame._jQueryInterface.call($(SELECTOR_DATA_TOGGLE))
})

/**
 * jQuery API
 * ====================================================
 */

$.fn[NAME] = IFrame._jQueryInterface
$.fn[NAME].Constructor = IFrame
$.fn[NAME].noConflict = function () {
  $.fn[NAME] = JQUERY_NO_CONFLICT
  return IFrame._jQueryInterface
}

export default IFrame
<commit_msg>add allowReload option for IFrame plugin<commit_after>/**
 * --------------------------------------------
 * AdminLTE IFrame.js
 * License MIT
 * --------------------------------------------
 */

import $ from 'jquery'

/**
 * Constants
 * ====================================================
 */

const NAME = 'IFrame'
const DATA_KEY = 'lte.iframe'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_DATA_TOGGLE = '[data-widget="iframe"]'
const SELECTOR_DATA_TOGGLE_CLOSE = '[data-widget="iframe-close"]'
const SELECTOR_DATA_TOGGLE_SCROLL_LEFT = '[data-widget="iframe-scrollleft"]'
const SELECTOR_DATA_TOGGLE_SCROLL_RIGHT = '[data-widget="iframe-scrollright"]'
const SELECTOR_DATA_TOGGLE_FULLSCREEN = '[data-widget="iframe-fullscreen"]'
const SELECTOR_CONTENT_WRAPPER = '.content-wrapper'
const SELECTOR_CONTENT_IFRAME = `${SELECTOR_CONTENT_WRAPPER} iframe`
const SELECTOR_TAB_NAV = `${SELECTOR_CONTENT_WRAPPER}.iframe-mode .nav`
const SELECTOR_TAB_NAVBAR_NAV = `${SELECTOR_CONTENT_WRAPPER}.iframe-mode .navbar-nav`
const SELECTOR_TAB_NAVBAR_NAV_ITEM = `${SELECTOR_TAB_NAVBAR_NAV} .nav-item`
const SELECTOR_TAB_NAVBAR_NAV_LINK = `${SELECTOR_TAB_NAVBAR_NAV} .nav-link`
const SELECTOR_TAB_CONTENT = `${SELECTOR_CONTENT_WRAPPER}.iframe-mode .tab-content`
const SELECTOR_TAB_EMPTY = `${SELECTOR_TAB_CONTENT} .tab-empty`
const SELECTOR_TAB_LOADING = `${SELECTOR_TAB_CONTENT} .tab-loading`
const SELECTOR_TAB_PANE = `${SELECTOR_TAB_CONTENT} .tab-pane`
const SELECTOR_SIDEBAR_MENU_ITEM = '.main-sidebar .nav-item > a.nav-link'
const SELECTOR_SIDEBAR_SEARCH_ITEM = '.sidebar-search-results .list-group-item'
const SELECTOR_HEADER_MENU_ITEM = '.main-header .nav-item a.nav-link'
const SELECTOR_HEADER_DROPDOWN_ITEM = '.main-header a.dropdown-item'
const CLASS_NAME_IFRAME_MODE = 'iframe-mode'
const CLASS_NAME_FULLSCREEN_MODE = 'iframe-mode-fullscreen'

const Default = {
  onTabClick(item) {
    return item
  },
  onTabChanged(item) {
    return item
  },
  onTabCreated(item) {
    return item
  },
  autoIframeMode: true,
  autoItemActive: true,
  autoShowNewTab: true,
  autoDarkMode: false,
  allowDuplicates: false,
  allowReload: true,
  loadingScreen: true,
  useNavbarItems: true,
  scrollOffset: 40,
  scrollBehaviorSwap: false,
  iconMaximize: 'fa-expand',
  iconMinimize: 'fa-compress'
}

/**
 * Class Definition
 * ====================================================
 */

class IFrame {
  constructor(element, config) {
    this._config = config
    this._element = element
    this._init()
  }

  // Public

  onTabClick(item) {
    this._config.onTabClick(item)
  }

  onTabChanged(item) {
    this._config.onTabChanged(item)
  }

  onTabCreated(item) {
    this._config.onTabCreated(item)
  }

  createTab(title, link, uniqueName, autoOpen) {
    let tabId = `panel-${uniqueName}`
    let navId = `tab-${uniqueName}`

    if (this._config.allowDuplicates) {
      tabId += `-${Math.floor(Math.random() * 1000)}`
      navId += `-${Math.floor(Math.random() * 1000)}`
    }

    const newNavItem = `
${title}
`
    $(SELECTOR_TAB_NAVBAR_NAV).append(unescape(escape(newNavItem)))

    const newTabItem = `<div class="tab-pane fade" id="${tabId}" role="tabpanel" aria-labelledby="${navId}"><iframe src="${link}"></iframe></div>`
    $(SELECTOR_TAB_CONTENT).append(unescape(escape(newTabItem)))

    if (autoOpen) {
      if (this._config.loadingScreen) {
        const $loadingScreen = $(SELECTOR_TAB_LOADING)
        $loadingScreen.fadeIn()
        $(`${tabId} iframe`).ready(() => {
          if (typeof this._config.loadingScreen === 'number') {
            this.switchTab(`#${navId}`)
            setTimeout(() => {
              $loadingScreen.fadeOut()
            }, this._config.loadingScreen)
          } else {
            this.switchTab(`#${navId}`)
            $loadingScreen.fadeOut()
          }
        })
      } else {
        this.switchTab(`#${navId}`)
      }
    }

    this.onTabCreated($(`#${navId}`))
  }

  openTabSidebar(item, autoOpen = this._config.autoShowNewTab) {
    let $item = $(item).clone()
    if ($item.attr('href') === undefined) {
      $item = $(item).parent('a').clone()
    }

    $item.find('.right, .search-path').remove()
    let title = $item.find('p').text()
    if (title === '') {
      title = $item.text()
    }

    const link = $item.attr('href')
    if (link === '#' || link === '' || link === undefined) {
      return
    }

    const uniqueName = link.replace('./', '').replace(/["#&'./:=?[\]]/gi, '-').replace(/(--)/gi, '')
    const navId = `tab-${uniqueName}`

    if (!this._config.allowDuplicates && $(`#${navId}`).length > 0) {
      return this.switchTab(`#${navId}`, this._config.allowReload)
    }

    if ((!this._config.allowDuplicates && $(`#${navId}`).length === 0) || this._config.allowDuplicates) {
      this.createTab(title, link, uniqueName, autoOpen)
    }
  }

  switchTab(item, reload = false) {
    const $item = $(item)
    const tabId = $item.attr('href')

    $(SELECTOR_TAB_EMPTY).hide()

    if (reload) {
      const $loadingScreen = $(SELECTOR_TAB_LOADING)
      if (this._config.loadingScreen) {
        $loadingScreen.show(0, () => {
          $(`${tabId} iframe`).attr('src', $(`${tabId} iframe`).attr('src')).ready(() => {
            if (this._config.loadingScreen) {
              if (typeof this._config.loadingScreen === 'number') {
                setTimeout(() => {
                  $loadingScreen.fadeOut()
                }, this._config.loadingScreen)
              } else {
                $loadingScreen.fadeOut()
              }
            }
          })
        })
      } else {
        $(`${tabId} iframe`).attr('src', $(`${tabId} iframe`).attr('src'))
      }
    }

    $(`${SELECTOR_TAB_NAVBAR_NAV} .active`).tab('dispose').removeClass('active')

    this._fixHeight()

    $item.tab('show')
    $item.parents('li').addClass('active')
    this.onTabChanged($item)

    if (this._config.autoItemActive) {
      this._setItemActive($(`${tabId} iframe`).attr('src'))
    }
  }

  removeActiveTab(type, element) {
    if (type == 'all') {
      $(SELECTOR_TAB_NAVBAR_NAV_ITEM).remove()
      $(SELECTOR_TAB_PANE).remove()
      $(SELECTOR_TAB_EMPTY).show()
    } else if (type == 'all-other') {
      $(`${SELECTOR_TAB_NAVBAR_NAV_ITEM}:not(.active)`).remove()
      $(`${SELECTOR_TAB_PANE}:not(.active)`).remove()
    } else if (type == 'only-this') {
      const $navClose = $(element)
      const $navItem = $navClose.parent('.nav-item')
      const $navItemParent = $navItem.parent()
      const navItemIndex = $navItem.index()
      const tabId = $navClose.siblings('.nav-link').attr('aria-controls')
      $navItem.remove()
      $(`#${tabId}`).remove()
      if ($(SELECTOR_TAB_CONTENT).children().length == $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).length) {
        $(SELECTOR_TAB_EMPTY).show()
      } else {
        const prevNavItemIndex = navItemIndex - 1
        this.switchTab($navItemParent.children().eq(prevNavItemIndex).find('a.nav-link'))
      }
    } else {
      const $navItem = $(`${SELECTOR_TAB_NAVBAR_NAV_ITEM}.active`)
      const $navItemParent = $navItem.parent()
      const navItemIndex = $navItem.index()
      $navItem.remove()
      $(`${SELECTOR_TAB_PANE}.active`).remove()
      if ($(SELECTOR_TAB_CONTENT).children().length == $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).length) {
        $(SELECTOR_TAB_EMPTY).show()
      } else {
        const prevNavItemIndex = navItemIndex - 1
        this.switchTab($navItemParent.children().eq(prevNavItemIndex).find('a.nav-link'))
      }
    }
  }

  toggleFullscreen() {
    if ($('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) {
      $(`${SELECTOR_DATA_TOGGLE_FULLSCREEN} i`).removeClass(this._config.iconMinimize).addClass(this._config.iconMaximize)
      $('body').removeClass(CLASS_NAME_FULLSCREEN_MODE)
      $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).height('100%')
      $(SELECTOR_CONTENT_WRAPPER).height('100%')
      $(SELECTOR_CONTENT_IFRAME).height('100%')
    } else {
      $(`${SELECTOR_DATA_TOGGLE_FULLSCREEN} i`).removeClass(this._config.iconMaximize).addClass(this._config.iconMinimize)
      $('body').addClass(CLASS_NAME_FULLSCREEN_MODE)
    }

    $(window).trigger('resize')
    this._fixHeight(true)
  }

  // Private

  _init() {
    const usingDefTab = ($(SELECTOR_TAB_CONTENT).children().length > 2)

    if (usingDefTab) {
      const $el = $(`${SELECTOR_TAB_PANE}:first-child`)
      $el.show()
      this._setItemActive($el.find('iframe').attr('src'))
    }

    this._setupListeners()
    this._fixHeight(!usingDefTab)
  }

  _initFrameElement() {
    if (window.frameElement && this._config.autoIframeMode) {
      const $body = $('body')
      $body.addClass(CLASS_NAME_IFRAME_MODE)

      if (this._config.autoDarkMode) {
        $body.addClass('dark-mode')
      }
    }
  }

  _navScroll(offset) {
    const leftPos = $(SELECTOR_TAB_NAVBAR_NAV).scrollLeft()
    $(SELECTOR_TAB_NAVBAR_NAV).animate({ scrollLeft: (leftPos + offset) }, 250, 'linear')
  }

  _setupListeners() {
    $(window).on('resize', () => {
      setTimeout(() => {
        this._fixHeight()
      }, 1)
    })
    if ($(SELECTOR_CONTENT_WRAPPER).hasClass(CLASS_NAME_IFRAME_MODE)) {
      $(document).on('click', `${SELECTOR_SIDEBAR_MENU_ITEM}, ${SELECTOR_SIDEBAR_SEARCH_ITEM}`, e => {
        e.preventDefault()
        this.openTabSidebar(e.target)
      })
      if (this._config.useNavbarItems) {
        $(document).on('click', `${SELECTOR_HEADER_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`, e => {
          e.preventDefault()
          this.openTabSidebar(e.target)
        })
      }
    }

    $(document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, e => {
      e.preventDefault()
      this.onTabClick(e.target)
      this.switchTab(e.target)
    })
    $(document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, e => {
      e.preventDefault()
      this.onTabClick(e.target)
      this.switchTab(e.target)
    })
    $(document).on('click', SELECTOR_DATA_TOGGLE_CLOSE, e => {
      e.preventDefault()
      let { target } = e

      if (target.nodeName == 'I') {
        target = e.target.offsetParent
      }

      this.removeActiveTab(target.attributes['data-type'] ? target.attributes['data-type'].nodeValue : null, target)
    })
    $(document).on('click', SELECTOR_DATA_TOGGLE_FULLSCREEN, e => {
      e.preventDefault()
      this.toggleFullscreen()
    })
    let mousedown = false
    let mousedownInterval = null
    $(document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_LEFT, e => {
      e.preventDefault()
      clearInterval(mousedownInterval)

      let { scrollOffset } = this._config

      if (!this._config.scrollBehaviorSwap) {
        scrollOffset = -scrollOffset
      }

      mousedown = true
      this._navScroll(scrollOffset)

      mousedownInterval = setInterval(() => {
        this._navScroll(scrollOffset)
      }, 250)
    })
    $(document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_RIGHT, e => {
      e.preventDefault()
      clearInterval(mousedownInterval)

      let { scrollOffset } = this._config

      if (this._config.scrollBehaviorSwap) {
        scrollOffset = -scrollOffset
      }

      mousedown = true
      this._navScroll(scrollOffset)

      mousedownInterval = setInterval(() => {
        this._navScroll(scrollOffset)
      }, 250)
    })
    $(document).on('mouseup', () => {
      if (mousedown) {
        mousedown = false
        clearInterval(mousedownInterval)
        mousedownInterval = null
      }
    })
  }

  _setItemActive(href) {
    $(`${SELECTOR_SIDEBAR_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`).removeClass('active')
    $(SELECTOR_HEADER_MENU_ITEM).parent().removeClass('active')

    const $headerMenuItem = $(`${SELECTOR_HEADER_MENU_ITEM}[href$="${href}"]`)
    const $headerDropdownItem = $(`${SELECTOR_HEADER_DROPDOWN_ITEM}[href$="${href}"]`)
    const $sidebarMenuItem = $(`${SELECTOR_SIDEBAR_MENU_ITEM}[href$="${href}"]`)

    $headerMenuItem.each((i, e) => {
      $(e).parent().addClass('active')
    })
    $headerDropdownItem.each((i, e) => {
      $(e).addClass('active')
    })
    $sidebarMenuItem.each((i, e) => {
      $(e).addClass('active')
      $(e).parents('.nav-treeview').prevAll('.nav-link').addClass('active')
    })
  }

  _fixHeight(tabEmpty = false) {
    if ($('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) {
      const windowHeight = $(window).height()
      const navbarHeight = $(SELECTOR_TAB_NAV).outerHeight()
      $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}, ${SELECTOR_CONTENT_IFRAME}`).height(windowHeight - navbarHeight)
      $(SELECTOR_CONTENT_WRAPPER).height(windowHeight)
    } else {
      const contentWrapperHeight = parseFloat($(SELECTOR_CONTENT_WRAPPER).css('height'))
      const navbarHeight = $(SELECTOR_TAB_NAV).outerHeight()
      if (tabEmpty == true) {
        setTimeout(() => {
          $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).height(contentWrapperHeight - navbarHeight)
        }, 50)
      } else {
        $(SELECTOR_CONTENT_IFRAME).height(contentWrapperHeight - navbarHeight)
      }
    }
  }

  // Static

  static _jQueryInterface(config) {
    if ($(SELECTOR_DATA_TOGGLE).length > 0) {
      let data = $(this).data(DATA_KEY)

      if (!data) {
        data = $(this).data()
      }

      const _options = $.extend({}, Default, typeof config === 'object' ? config : data)
      localStorage.setItem('AdminLTE:IFrame:Options', JSON.stringify(_options))

      const plugin = new IFrame($(this), _options)

      $(this).data(DATA_KEY, typeof config === 'object' ? config : data)

      if (typeof config === 'string' && /createTab|openTabSidebar|switchTab|removeActiveTab/.test(config)) {
        plugin[config]()
      }
    } else {
      new IFrame($(this), JSON.parse(localStorage.getItem('AdminLTE:IFrame:Options')))._initFrameElement()
    }
  }
}

/**
 * Data API
 * ====================================================
 */

$(window).on('load', () => {
  IFrame._jQueryInterface.call($(SELECTOR_DATA_TOGGLE))
})

/**
 * jQuery API
 * ====================================================
 */

$.fn[NAME] = IFrame._jQueryInterface
$.fn[NAME].Constructor = IFrame
$.fn[NAME].noConflict = function () {
  $.fn[NAME] = JQUERY_NO_CONFLICT
  return IFrame._jQueryInterface
}

export default IFrame
<|endoftext|>


<commit_before>var pluginSettings;

function update_plugin_settings() {
	AJS.$.get(contextPath + "/plugins/servlet/foresight-settings", function(data) {
		pluginSettings = JSON.parse(data);
	});
}

function update_description_types() {
	var descriptionType = AJS.$('#dependencyDescriptionTypes').val();
	d3.selectAll(".dependency-link").text(function(data) {
		var linkLabel;
		switch (descriptionType) {
		case 'none':
			linkLabel = "";
			break;
		case 'inward':
			linkLabel = data.inward;
			break;
		case 'outward':
			linkLabel = data.outward;
			break;
		}
		return linkLabel;
	});
}

function show_graph() {

	update_plugin_settings();

	var issue_id=AJS.$("input[name=id]").val();
	var includeInwardLinks=AJS.$("#issue-dependency-viewer-form input[name=includeInward]").is(':checked');
	var includeOutwardLinks=AJS.$("#issue-dependency-viewer-form input[name=includeOutward]").is(':checked');

	AJS.$.get(contextPath + "/plugins/servlet/foresight-dependency-graph"
			+ "?currentIssueId="+issue_id
			+ "&includeOutward="+includeOutwardLinks
			+ "&includeInward="+includeInwardLinks, function(data) {

		// clean up old svg object
		d3.select("#issue-dependency-viewer-graph").remove();
		var container = d3.select('#issue-dependency-viewer-graph-container');

		var svg = container.append('svg:svg')
			.attr("id", "issue-dependency-viewer-graph")
			.attr("width", 900)
			.attr("height", 500);

		var graph = JSON.parse(data);

		var links = graph.links;
		var nodes = graph.nodes;

		// link the actual nodes
		links.forEach(function(link) {
			  link.source = nodes[link.source];
			  link.target = nodes[link.target];
		});

		// create the layout
		var force = d3.layout.force()
		    .nodes(nodes)
		    .links(links)
		    .size([900, 500])
		    .linkDistance(120)
		    .charge(-150)
		    .gravity(.05)
		    .distance(100)
		    .on("tick", tick)
		    .start();

		var node_drag = d3.behavior.drag()
			.on("dragstart", dragstart)
			.on("drag", dragmove)
			.on("dragend", dragend);

	    function dragstart(d, i) {
	        force.stop();
	    }

	    function dragmove(d, i) {
	        d.px += d3.event.dx;
	        d.py += d3.event.dy;
	        d.x += d3.event.dx;
	        d.y += d3.event.dy;
	        tick();
	    }

	    function dragend(d, i) {
	        d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
	        tick();
	        force.resume();
	    }

		svg.append("svg:defs").selectAll("marker")
		    .data(["resolved"])
		  .enter().append("svg:marker")
		    .attr("id", String)
		    .attr("viewBox", "0 -5 10 10")
		    .attr("refX", 15)
		    .attr("refY", -1.5)
		    .attr("markerWidth", 6)
		    .attr("markerHeight", 6)
		    .attr("orient", "auto")
		  .append("svg:path")
		    .attr("d", "M0,-5L10,0L0,5");

		var path = svg.append("svg:g").selectAll("path")
		    .data(force.links())
		  .enter().append("svg:path")
		    .attr("class", function(d) { return "link normal" })
		    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

		var circle = svg.append("svg:g").selectAll("circle")
		    .data(force.nodes())
		    .enter().append("svg:circle")
		    .attr("class", "circle")
		    .attr("fill", function(data) {
		    	if (issue_id == data.key) {
		    		return "#4552E6";
		    	}
		    	else {
		    		return pluginSettings.nodecolors[data.type];
		    	}
		    	})
		    .attr("r", 7)
		    .call(node_drag);

		var labels = svg.selectAll('text')
		    .data(graph.links)
		  .enter().append('text')
		    .attr("x", function(d) { return (d.source.y + d.target.y) / 2; })
		    .attr("y", function(d) { return (d.source.x + d.target.x) / 2; })
		    .attr("text-anchor", "middle")
		    .attr("class", "dependency-link");

		var link = svg.append("svg:g").selectAll("g")
		    .data(force.nodes())
		    .enter().append("svg:g");

		var text = svg.append("svg:g").selectAll("g")
		    .data(force.nodes())
		  .enter().append("svg:g");

		// show the task key
		text.append("svg:text")
		    .attr("x", 8)
		    .attr("y", ".31em")
		    .attr("class", "shadow")
		    .text(function(d) { return d.name; });

		text.append("svg:text")
		    .attr("x", 8)
		    .attr("y", ".31em")
		    .text(function(d) { return d.name; });

		update_description_types();

		// curve the arcs between the nodes to correctly show cycles.
		function tick() {
		  path.attr("d", function(d) {
		    var dx = d.target.x - d.source.x,
		        dy = d.target.y - d.source.y,
		        dr = Math.sqrt(dx * dx + dy * dy);
		    return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
		  });

		  circle.attr("transform", function(d) {
		    return "translate(" + d.x + "," + d.y + ")";
		  });

		  text.attr("transform", function(d) {
		    return "translate(" + d.x + "," + d.y + ")";
		  });

		  labels.attr("x", function(d) { return (d.source.x + d.target.x) / 2; })
	        .attr("y", function(d) { return (d.source.y + d.target.y) / 2; })
		}
  });
}

AJS.$(document).ready(function() {

	// on change functions of the show inward/outward checkboxes
	AJS.$("#issue-dependency-viewer-form input[name=includeInward]").change(function(){
		show_graph();
	});
	AJS.$("#issue-dependency-viewer-form input[name=includeOutward]").change(function(){
		show_graph();
	});

	// on change function for the description types drop-down.
	AJS.$("#dependencyDescriptionTypes").change(function(){
		update_description_types();
	});
});<commit_msg>dependency links too large with firefox<commit_after>var pluginSettings;

function update_plugin_settings() {
	AJS.$.get(contextPath + "/plugins/servlet/foresight-settings", function(data) {
		pluginSettings = JSON.parse(data);
	});
}

function update_description_types() {
	var descriptionType = AJS.$('#dependencyDescriptionTypes').val();
	d3.selectAll(".dependency-link").text(function(data) {
		var linkLabel;
		switch (descriptionType) {
		case 'none':
			linkLabel = "";
			break;
		case 'inward':
			linkLabel = data.inward;
			break;
		case 'outward':
			linkLabel = data.outward;
			break;
		}
		return linkLabel;
	});
}

function show_graph() {

	update_plugin_settings();

	var issue_id=AJS.$("input[name=id]").val();
	var includeInwardLinks=AJS.$("#issue-dependency-viewer-form input[name=includeInward]").is(':checked');
	var includeOutwardLinks=AJS.$("#issue-dependency-viewer-form input[name=includeOutward]").is(':checked');

	AJS.$.get(contextPath + "/plugins/servlet/foresight-dependency-graph"
			+ "?currentIssueId="+issue_id
			+ "&includeOutward="+includeOutwardLinks
			+ "&includeInward="+includeInwardLinks, function(data) {

		// clean up old svg object
		d3.select("#issue-dependency-viewer-graph").remove();
		var container = d3.select('#issue-dependency-viewer-graph-container');

		var svg = container.append('svg:svg')
			.attr("id", "issue-dependency-viewer-graph")
			.attr("width", 900)
			.attr("height", 500);

		var graph = JSON.parse(data);

		var links = graph.links;
		var nodes = graph.nodes;

		// link the actual nodes
		links.forEach(function(link) {
			  link.source = nodes[link.source];
			  link.target = nodes[link.target];
		});

		// create the layout
		var force = d3.layout.force()
		    .nodes(nodes)
		    .links(links)
		    .size([900, 500])
		    .linkDistance(120)
		    .charge(-150)
		    .gravity(.05)
		    .distance(100)
		    .on("tick", tick)
		    .start();

		var node_drag = d3.behavior.drag()
			.on("dragstart", dragstart)
			.on("drag", dragmove)
			.on("dragend", dragend);

	    function dragstart(d, i) {
	        force.stop();
	    }

	    function dragmove(d, i) {
	        d.px += d3.event.dx;
	        d.py += d3.event.dy;
	        d.x += d3.event.dx;
	        d.y += d3.event.dy;
	        tick();
	    }

	    function dragend(d, i) {
	        d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
	        tick();
	        force.resume();
	    }

		svg.append("svg:defs").selectAll("marker")
		    .data(["resolved"])
		  .enter().append("svg:marker")
		    .attr("id", String)
		    .attr("viewBox", "0 -5 10 10")
		    .attr("refX", 15)
		    .attr("refY", -1.5)
		    .attr("markerWidth", 6)
		    .attr("markerHeight", 6)
		    .attr("orient", "auto")
		  .append("svg:path")
		    .attr("d", "M0,-5L10,0L0,5");

		var path = svg.append("svg:g").selectAll("path")
	    	.data(force.links())
	      .enter().append("svg:path")
	        .attr("class", function(d) { return "link normal" })
	        .attr("fill", "none")
	        .attr("stroke", "#666")
	        .attr("stroke-width", "1.5px")
	        .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

		var circle = svg.append("svg:g").selectAll("circle")
		    .data(force.nodes())
		    .enter().append("svg:circle")
		    .attr("class", "circle")
		    .attr("fill", function(data) {
		    	if (issue_id == data.key) {
		    		return "#4552E6";
		    	}
		    	else {
		    		return pluginSettings.nodecolors[data.type];
		    	}
		    	})
		    .attr("r", 7)
		    .call(node_drag);

		var labels = svg.selectAll('text')
		    .data(graph.links)
		  .enter().append('text')
		    .attr("x", function(d) { return (d.source.y + d.target.y) / 2; })
		    .attr("y", function(d) { return (d.source.x + d.target.x) / 2; })
		    .attr("text-anchor", "middle")
		    .attr("class", "dependency-link");

		var link = svg.append("svg:g").selectAll("g")
		    .data(force.nodes())
		    .enter().append("svg:g");

		var text = svg.append("svg:g").selectAll("g")
		    .data(force.nodes())
		  .enter().append("svg:g");

		// show the task key
		text.append("svg:text")
		    .attr("x", 8)
		    .attr("y", ".31em")
		    .attr("class", "shadow")
		    .text(function(d) { return d.name; });

		text.append("svg:text")
		    .attr("x", 8)
		    .attr("y", ".31em")
		    .text(function(d) { return d.name; });

		update_description_types();

		// curve the arcs between the nodes to correctly show cycles.
		function tick() {
		  path.attr("d", function(d) {
		    var dx = d.target.x - d.source.x,
		        dy = d.target.y - d.source.y,
		        dr = Math.sqrt(dx * dx + dy * dy);
		    return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
		  });

		  circle.attr("transform", function(d) {
		    return "translate(" + d.x + "," + d.y + ")";
		  });

		  text.attr("transform", function(d) {
		    return "translate(" + d.x + "," + d.y + ")";
		  });

		  labels.attr("x", function(d) { return (d.source.x + d.target.x) / 2; })
	        .attr("y", function(d) { return (d.source.y + d.target.y) / 2; })
		}
  });
}

AJS.$(document).ready(function() {

	// on change functions of the show inward/outward checkboxes
	AJS.$("#issue-dependency-viewer-form input[name=includeInward]").change(function(){
		show_graph();
	});
	AJS.$("#issue-dependency-viewer-form input[name=includeOutward]").change(function(){
		show_graph();
	});

	// on change function for the description types drop-down.
	AJS.$("#dependencyDescriptionTypes").change(function(){
		update_description_types();
	});
});<|endoftext|>


<commit_before>(function(){

  var initTimerId;
  var displayedStep;
  var lastLocation;

  var fieldsLoaded = function(){
    var buttonContainer = document.querySelector("div.buttons-container");
    if(buttonContainer){
      return true;
    }else{
      return false;
    }
  }

  var sortFieldsInSteps = function(){
    var fields = document.querySelectorAll(".field-group");
    var wizardSteps = [];
    Array.prototype.forEach.call(fields, function(field){
      console.log(field);
      var descriptionParagraph = field.querySelector(".description p");
      if(descriptionParagraph){
        //test to see if there is the specific tag in field description
        var matches = descriptionParagraph.textContent.match(/@@(.*)@@/i)
        if(matches){
          console.log("found Wizard Step Title : " + matches[1]);
          //remove the tag from description
          descriptionParagraph.textContent = descriptionParagraph.textContent.replace(/@@(.*)@@/i, "");

          //test if wizard step is not know yet
          var step = wizardSteps.find(function(step){ return step.name == matches[1];});
          if(!step){
            step = {"name" : matches[1], "fields" : []};
            wizardSteps.push(step);
          }

          //append it to that step
          step.fields.push(field);
        }else{
          //show the field
          field.style.display = 'block';
        }
      }
    });

    return wizardSteps;
  }

  var reLayoutFields = function(wizardSteps){

    console.log(wizardSteps);

    var requestForm = document.querySelector("form");
    var nativeButtons = document.querySelector("form div.buttons");

    wizardSteps.forEach(function(step,index,steps){

      var stepDiv = document.createElement("div");
      stepDiv.classList.add("wizard-step");
      var stepTitle = document.createElement("h3");

      stepTitle.textContent = "Etape " + (index +1) + " / " + steps.length + " : " +step.name;
      stepDiv.appendChild(stepTitle);
      requestForm.appendChild(stepDiv);
      step.fields.forEach(function(field){
        stepDiv.appendChild(field);
        field.style.display = 'block';
      });

      var stepButtons = document.createElement("div");
      stepButtons.classList.add("buttons");

      console.log("processing step index : " + index);

      if(index == steps.length -1){

        var stepPrevious = document.createElement("button");
        stepPrevious.classList.add("aui-button", "aui-button-link");
        stepPrevious.textContent = "Précédent";

        stepPrevious.addEventListener("click",function(e){
          displayedStep--;
          displayCurrentStep();
          e.preventDefault();
        });

        nativeButtons.insertBefore(stepPrevious,nativeButtons.querySelector("div"));

        stepDiv.appendChild(nativeButtons);

      }else{

        var stepNext = document.createElement("button");
        stepNext.classList.add("aui-button");
        stepNext.textContent = "Suivant";

        stepNext.addEventListener("click",function(e){
          displayedStep++;
          displayCurrentStep();
          e.preventDefault();
        });

        stepButtons.appendChild(stepNext);

        if(index != 0){
          var stepPrevious = document.createElement("button");
          stepPrevious.classList.add("aui-button", "aui-button-link");
          stepPrevious.textContent = "Précédent";

          stepPrevious.addEventListener("click",function(e){
            displayedStep--;
            displayCurrentStep();
            e.preventDefault();
          });
          stepButtons.appendChild(stepPrevious);
        }

        stepDiv.appendChild(stepButtons);

      }

    });
  }

  var displayCurrentStep = function(){
    var stepsDivs = document.querySelectorAll(".wizard-step");
    Array.prototype.forEach.call(stepsDivs, function(elem){elem.style.display = 'none';});
    console.log(stepsDivs);
    console.log(displayedStep);
    stepsDivs[displayedStep].style.display='block';
    //TODO consider scrolling to the title of that step
  }

  var initView = function(){
    if(fieldsLoaded()){
      console.log("trying to setup display");
      window.clearInterval(initTimerId);
      reLayoutFields(sortFieldsInSteps());
      displayedStep = 0;
      displayCurrentStep();
    }
  }

  /*window.addEventListener("load",function(){
    console.log("jsd-wizard plugin fired up !");
    initTimerId = window.setInterval(initView, 100);
  });*/

  var fireUp = function(){
    if(!lastLocation || lastLocation != window.location.href){
      lastLocation = window.location.href;
      console.log(lastLocation);
      if(lastLocation.indexOf("create") != -1){
        console.log("jsd-wizard plugin fired up !");
        initTimerId = window.setInterval(initView, 100);
      }
    }
  }

  setInterval(fireUp,100);

})();
<commit_msg>fix error on non wizzard requests<commit_after>(function(){

  var initTimerId;
  var displayedStep;
  var lastLocation;

  var fieldsLoaded = function(){
    var buttonContainer = document.querySelector("div.buttons-container");
    if(buttonContainer){
      return true;
    }else{
      return false;
    }
  }

  var sortFieldsInSteps = function(){
    var fields = document.querySelectorAll(".field-group");
    var wizardSteps = [];
    Array.prototype.forEach.call(fields, function(field){
      console.log(field);
      var descriptionParagraph = field.querySelector(".description p");
      if(descriptionParagraph){
        //test to see if there is the specific tag in field description
        var matches = descriptionParagraph.textContent.match(/@@(.*)@@/i)
        if(matches){
          console.log("found Wizard Step Title : " + matches[1]);
          //remove the tag from description
          descriptionParagraph.textContent = descriptionParagraph.textContent.replace(/@@(.*)@@/i, "");

          //test if wizard step is not know yet
          var step = wizardSteps.find(function(step){ return step.name == matches[1];});
          if(!step){
            step = {"name" : matches[1], "fields" : []};
            wizardSteps.push(step);
          }

          //append it to that step
          step.fields.push(field);
        }else{
          //show the field
          field.style.display = 'block';
        }
      }
    });

    return wizardSteps;
  }

  var reLayoutFields = function(wizardSteps){

    console.log(wizardSteps);

    var requestForm = document.querySelector("form");
    var nativeButtons = document.querySelector("form div.buttons");

    wizardSteps.forEach(function(step,index,steps){

      var stepDiv = document.createElement("div");
      stepDiv.classList.add("wizard-step");
      var stepTitle = document.createElement("h3");

      stepTitle.textContent = "Etape " + (index +1) + " / " + steps.length + " : " +step.name;
      stepDiv.appendChild(stepTitle);
      requestForm.appendChild(stepDiv);
      step.fields.forEach(function(field){
        stepDiv.appendChild(field);
        field.style.display = 'block';
      });

      var stepButtons = document.createElement("div");
      stepButtons.classList.add("buttons");

      console.log("processing step index : " + index);

      if(index == steps.length -1){

        var stepPrevious = document.createElement("button");
        stepPrevious.classList.add("aui-button", "aui-button-link");
        stepPrevious.textContent = "Précédent";

        stepPrevious.addEventListener("click",function(e){
          displayedStep--;
          displayCurrentStep();
          e.preventDefault();
        });

        nativeButtons.insertBefore(stepPrevious,nativeButtons.querySelector("div"));

        stepDiv.appendChild(nativeButtons);

      }else{

        var stepNext = document.createElement("button");
        stepNext.classList.add("aui-button");
        stepNext.textContent = "Suivant";

        stepNext.addEventListener("click",function(e){
          displayedStep++;
          displayCurrentStep();
          e.preventDefault();
        });

        stepButtons.appendChild(stepNext);

        if(index != 0){
          var stepPrevious = document.createElement("button");
          stepPrevious.classList.add("aui-button", "aui-button-link");
          stepPrevious.textContent = "Précédent";

          stepPrevious.addEventListener("click",function(e){
            displayedStep--;
            displayCurrentStep();
            e.preventDefault();
          });
          stepButtons.appendChild(stepPrevious);
        }

        stepDiv.appendChild(stepButtons);

      }

    });
  }

  var displayCurrentStep = function(){
    var stepsDivs = document.querySelectorAll(".wizard-step");
    if(stepsDivs.length > 0){
      Array.prototype.forEach.call(stepsDivs, function(elem){elem.style.display = 'none';});
      stepsDivs[displayedStep].style.display='block';
      //TODO consider scrolling to the title of that step
    }
  }

  var initView = function(){
    if(fieldsLoaded()){
      console.log("trying to setup display");
      window.clearInterval(initTimerId);
      reLayoutFields(sortFieldsInSteps());
      displayedStep = 0;
      displayCurrentStep();
    }
  }

  /*window.addEventListener("load",function(){
    console.log("jsd-wizard plugin fired up !");
    initTimerId = window.setInterval(initView, 100);
  });*/

  var fireUp = function(){
    if(!lastLocation || lastLocation != window.location.href){
      lastLocation = window.location.href;
      console.log(lastLocation);
      if(lastLocation.indexOf("create") != -1){
        console.log("jsd-wizard plugin fired up !");
        initTimerId = window.setInterval(initView, 100);
      }
    }
  }

  setInterval(fireUp,100);

})();
<|endoftext|>


<commit_before>/*

	tdapp_all.js

*/
require('./tdapp.js');
require('./tdapp_firebase.js');
require('./tdapp_factories.js');
require('./tdapp_service_backend.js');
require('./tdapp_service_autologin.js');
require('./tdapp_controller_reg.js');
require('./tdapp_controller_settings.js');
require('./tdapp_controller_resetpwd.js');
require('./tdapp_controller_auth.js');
require('./tdapp_controller_main.js');
<commit_msg>Bugfix.<commit_after>/*

	tdapp_all.js

*/
require('./tdapp.js');
require('./tdapp_firebase.js');
require('./tdapp_factories.js');
require('./tdapp_service_autologin.js');
require('./tdapp_service_backend.js');
require('./tdapp_controller_reg.js');
require('./tdapp_controller_settings.js');
require('./tdapp_controller_resetpwd.js');
require('./tdapp_controller_auth.js');
require('./tdapp_controller_main.js');
<|endoftext|>


<commit_before>/*
This file gets loaded along with the rest of Ext library at the initial load
At this time the following constants have been set by Rails:

  Netzke.RelativeUrlRoot - set to ActionController::Base.config.relative_url_root
  Netzke.RelativeExtUrl - URL to ext files
*/

// Initial stuff
Ext.BLANK_IMAGE_URL = Netzke.RelativeExtUrl + "/resources/images/default/s.gif";
Ext.ns('Ext.netzke'); // namespace for extensions that depend on Ext

Netzke.isLoading=function () {
  return Netzke.runningRequests!=0;
}
Netzke.runningRequests=0

Netzke.deprecationWarning = function(msg){
  if (typeof console == 'undefined') {
    // no console defined
  } else {
    console.info("Netzke: " + msg);
  }
};

Ext.ns('Netzke.page'); // namespace for all component instantces on the page
Ext.ns('Netzke.classes'); // namespace for all component classes
Ext.ns('Netzke.classes.Core'); // namespace for all component classes

Netzke.chainApply = function(){
  var res = {};
  Ext.each(arguments, function(o){
    Ext.apply(res, o);
  });
  return res;
};

// Some Ruby-ish String extensions
// from http://code.google.com/p/inflection-js/
String.prototype.camelize=function(lowFirstLetter)
{
  var str=this; //.toLowerCase();
  var str_path=str.split('/');
  for(var i=0;i<str_path.length;i++)
  {
    var str_arr=str_path[i].split('_');
    var initX=((lowFirstLetter&&i+1==str_path.length)?(1):(0));
    for(var x=initX;x<str_arr.length;x++)
      str_arr[x]=str_arr[x].charAt(0).toUpperCase()+str_arr[x].substring(1);
    str_path[i]=str_arr.join('');
  }
  str=str_path.join('::');
  return str;
};

String.prototype.capitalize=function()
{
  var str=this.toLowerCase();
  str=str.substring(0,1).toUpperCase()+str.substring(1);
  return str;
};

String.prototype.humanize=function(lowFirstLetter)
{
  var str=this.toLowerCase();
  str=str.replace(new RegExp('_id','g'),'');
  str=str.replace(new RegExp('_','g'),' ');
  if(!lowFirstLetter)str=str.capitalize();
  return str;
};

// This one is borrowed from prototype.js
String.prototype.underscore = function() {
  return this.replace(/::/g, '/')
             .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
             .replace(/([a-z\d])([A-Z])/g, '$1_$2')
             .replace(/-/g, '_')
             .toLowerCase();
};

// Usefull when using mixins
Netzke.aliasMethodChain = function(klass, method, feature) {
  klass[method + "Without" + feature.capitalize()] = klass[method];
  klass[method] = klass[method + "With" + feature.capitalize()];
};

Netzke.cache = [];

// Registering a Netzke component
Netzke.reg = function(xtype, klass) {
  if (!Ext.ComponentMgr.types[xtype]) {
    Ext.reg(xtype, klass);
    Netzke.cache.push(xtype);
  }
};

Netzke.classes.Core.Mixin = {};

// Properties/methods common to all Netzke component classes
Netzke.componentMixin = function(receiver){
  return Ext.apply({
    isNetzke: true, // to distinguish Netzke components from regular Ext components
    latestResult: {}, // latest result returned from the server via an API call
    /*
    Overriding the constructor to only apply an "alias method chain" to initComponent
    */
    constructor: function(config){
      Netzke.aliasMethodChain(this, "initComponent", "netzke");
      receiver.superclass.constructor.call(this, config);
    },

    /*
    Dynamically creates methods for api points, so that we could later call them like: this.myEndpointMethod()
    */
    processEndpoints: function(){
      var endpoints = this.endpoints || [];
      endpoints.push('deliver_component'); // all Netzke components get this endpoint
      Ext.each(endpoints, function(intp){
        this[intp.camelize(true)] = function(args, callback, scope){ this.callServer(intp, args, callback, scope); }
      }, this);
    },

    /*
    Detects component placeholders in the passed object (typically, "items"),
    and merges them with the corresponding config from this.components.
    This way it becomes ready to be instantiated properly by Ext.
    */
    detectComponents: function(o){
      if (Ext.isObject(o)) {
        if (o.items) this.detectComponents(o.items);
      } else if (Ext.isArray(o)) {
        var a = o;
        Ext.each(a, function(el, i){
          if (el.component) {
            a[i] = Ext.apply(this.components[el.component.camelize(true)], el);
            delete a[i].component;
          } else if (el.items) this.detectComponents(el.items);
        }, this);
      }
    },

    /*
    Evaluates CSS
    */
    evalCss : function(code){
      var linkTag = document.createElement('style');
      linkTag.type = 'text/css';
      linkTag.innerHTML = code;
      document.body.appendChild(linkTag);
    },

    /*
    Evaluates JS
    */
    evalJs : function(code){
      eval(code);
    },

    /*
    Gets id in the context of provided parent.
    For example, the components "properties", being a child of "books" has global id "books__properties",
    which *is* its widegt's real id. This methods, with the instance of "books" passed as parameter,
    returns "properties".
    */
    localId : function(parent){
      return this.id.replace(parent.id + "__", "");
    },

    /*
    Executes a bunch of methods. This method is called almost every time a communication to the server takes place.
    Thus the server side of a component can provide any set of commands to its client side.
    Args:
      - instructions: array of methods, in the order of execution.
        Each item is an object in one of the following 2 formats:
          1) {method1:args1, method2:args2}, where methodN is a name of a public method of this component; these methods are called in no particular order
          2) {component:component_id, methods:arrayOfMethods}, used for recursive call to bulkExecute on some child component

    Example:
      - [
          // the same as this.feedback("Your order is accepted")
          {feedback: "You order is accepted"},

          // the same as this.getChildComponent('users').bulkExecute([{setTitle:'Suprise!'}, {setDisabled:true}])
          {component:'users', methods:[{setTitle:'Suprise!'}, {setDisabled:true}] },

          // ... etc:
          {updateStore:{records:[[1, 'Name1'],[2, 'Name2']], total:10}},
          {setColums:[{},{}]},
          {setMenus:[{},{}]},
          ...
        ]
    */
    bulkExecute : function(instructions){
      if (Ext.isArray(instructions)) {
        Ext.each(instructions, function(instruction){ this.bulkExecute(instruction)}, this);
      } else {
        for (var instr in instructions) {
          if (Ext.isFunction(this[instr])) {
            // Executing the method. If arguments are an array, expand that into arguments.
            this[instr].apply(this, Ext.isArray(instructions[instr]) ? instructions[instr] : [instructions[instr]]);
          } else {
            var childComponent = this.getChildComponent(instr);
            if (childComponent) {
              childComponent.bulkExecute(instructions[instr]);
            } else {
              throw "Netzke: Unknown method or child component '" + instr +"' in component '" + this.id + "'"
            }
          }
        }
      }
    },

    // Returns API url based on provided API point
    buildApiUrl: function(endpoint){
      Netzke.deprecationWarning("buildApiUrl() is deprecated. Use endpointUrl() first");
      return this.endpointUrl(endpoint);
    },

    endpointUrl: function(endpoint){
      return Netzke.RelativeUrlRoot + "/netzke/" + this.id + "__" + endpoint;
    },

    // Does the call to the server and processes the response
    callServer : function(intp, params, callback, scope){
      Netzke.runningRequests++;
      if (!params) params = {};
        Ext.Ajax.request({
        params: params,
        url: this.endpointUrl(intp),
        callback: function(options, success, response){
          if (success && response.responseText) {
            // execute commands from server
            this.bulkExecute(Ext.decode(response.responseText));

            // provide callback if needed
            if (typeof callback == 'function') {
              if (!scope) scope = this;
              callback.apply(scope, [this.latestResult]);
            }
          }
        },
        scope : this
      });
      Netzke.runningRequests--;
    },

    setResult: function(result) {
      this.latestResult = result;
    }
  }, Netzke.classes.Core.Mixin);
};

// Netzke extensions for Ext.Container
Ext.override(Ext.Container, {
  // Instantiates an component by its config. If it appears to be a window, shows it instead of adding as item.
  // TODO: there must be a method to just instantiate a component, but not to add/show it instantly.
  instantiateChild : function(config){
    var instance = Ext.create(config);
    if (instance.isXType("window")) {
      instance.show();
    } else {
      this.remove(this.getNetzkeComponent()); // first delete previous component
      this.add(instance);

      // Sometimes a child is getting loaded into a hidden container...
      if (this.isVisible()) {
        this.doLayout();
      } else {
        this.on('show', function(cmp){cmp.doLayout();}, {single: true});
      }

    }
    return instance;
  },

  /**
    Get Netzke component that this Ext.Container is part of (*not* the parent component, for which call getParent)
    It searches up the Ext.Container hierarchy until it finds a Container that has isNetzke property set to true
    (or until it reaches the top).
  */
  getOwnerComponent : function(){
    if (this.initialConfig.isNetzke) {
      return this;
    } else {
      if (this.ownerCt){
        return this.ownerCt.getOwnerComponent()
      } else {
        return null
      }
    }
  },

  // Get the component that we are hosting
  getNetzkeComponent: function(){
    return this.items ? this.items.first() : null; // need this check in case when the container is not yet rendered, like an inactive tab in the TabPanel
  },

  // Remove the child
  removeChild : function(){
    this.remove(this.getNetzkeComponent());
  }
});

// Feedback Ghost
Netzke.FeedbackGhost = function(){};
Ext.apply(Netzke.FeedbackGhost.prototype, {
  showFeedback: function(msg){
    var createBox = function(s, l){
        return ['
',
                '

',
                '

', s, '

',
                '

',
                '
'].join('');
    }

    var showBox = function(msg, lvl){
      if (!lvl) {lvl = 'notice'};

      var msgCt = Ext.get('netzke-feedback') || Ext.DomHelper.insertFirst(document.body, {id: 'netzke-feedback', 'class':'netzke-feedback'}, true);

      var m = Ext.DomHelper.append(msgCt, {html:createBox(msg,lvl)}, true);
      m.slideIn('t').pause(2).ghost("b", {remove:true});
    }

    if (typeof msg != 'string') {
      var compoundMsg = "";
      Ext.each(msg, function(m){
        compoundMsg += m.msg + '
';
      });
      if (compoundMsg != "") showBox(compoundMsg, null); // the second parameter will be level
    } else {
      showBox(msg);
    }
  }
});
<commit_msg>Minor<commit_after>/*
This file gets loaded along with the rest of Ext library at the initial load
At this time the following constants have been set by Rails:

  Netzke.RelativeUrlRoot - set to ActionController::Base.config.relative_url_root
  Netzke.RelativeExtUrl - URL to ext files
*/

// Initial stuff
Ext.BLANK_IMAGE_URL = Netzke.RelativeExtUrl + "/resources/images/default/s.gif";
Ext.ns('Ext.netzke'); // namespace for extensions that depend on Ext

Netzke.isLoading=function () {
  return Netzke.runningRequests!=0;
}
Netzke.runningRequests=0

Netzke.deprecationWarning = function(msg){
  if (typeof console == 'undefined') {
    // no console defined
  } else {
    console.info("Netzke: " + msg);
  }
};

Ext.ns('Netzke.page'); // namespace for all component instantces on the page
Ext.ns('Netzke.classes'); // namespace for all component classes
Ext.ns('Netzke.classes.Core'); // namespace for all component classes

Netzke.chainApply = function(){
  var res = {};
  Ext.each(arguments, function(o){
    Ext.apply(res, o);
  });
  return res;
};

// Some Ruby-ish String extensions
// from http://code.google.com/p/inflection-js/
String.prototype.camelize=function(lowFirstLetter)
{
  var str=this; //.toLowerCase();
  var str_path=str.split('/');
  for(var i=0;i<str_path.length;i++)
  {
    var str_arr=str_path[i].split('_');
    var initX=((lowFirstLetter&&i+1==str_path.length)?(1):(0));
    for(var x=initX;x<str_arr.length;x++)
      str_arr[x]=str_arr[x].charAt(0).toUpperCase()+str_arr[x].substring(1);
    str_path[i]=str_arr.join('');
  }
  str=str_path.join('::');
  return str;
};

String.prototype.capitalize=function()
{
  var str=this.toLowerCase();
  str=str.substring(0,1).toUpperCase()+str.substring(1);
  return str;
};

String.prototype.humanize=function(lowFirstLetter)
{
  var str=this.toLowerCase();
  str=str.replace(new RegExp('_id','g'),'');
  str=str.replace(new RegExp('_','g'),' ');
  if(!lowFirstLetter)str=str.capitalize();
  return str;
};

// This one is borrowed from prototype.js
String.prototype.underscore = function() {
  return this.replace(/::/g, '/')
             .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
             .replace(/([a-z\d])([A-Z])/g, '$1_$2')
             .replace(/-/g, '_')
             .toLowerCase();
};

// Usefull when using mixins
Netzke.aliasMethodChain = function(klass, method, feature) {
  klass[method + "Without" + feature.capitalize()] = klass[method];
  klass[method] = klass[method + "With" + feature.capitalize()];
};

Netzke.cache = [];

// Registering a Netzke component
Netzke.reg = function(xtype, klass) {
  if (!Ext.ComponentMgr.types[xtype]) {
    Ext.reg(xtype, klass);
    Netzke.cache.push(xtype);
  }
};

Netzke.classes.Core.Mixin = {};

// Properties/methods common to all Netzke component classes
Netzke.componentMixin = function(receiver){
  return Ext.apply({
    isNetzke: true, // to distinguish Netzke components from regular Ext components
    latestResult: {}, // latest result returned from the server via an API call
    /*
    Overriding the constructor to only apply an "alias method chain" to initComponent
    */
    constructor: function(config){
      Netzke.aliasMethodChain(this, "initComponent", "netzke");
      receiver.superclass.constructor.call(this, config);
    },

    /*
    Dynamically creates methods for api points, so that we could later call them like: this.myEndpointMethod()
    */
    processEndpoints: function(){
      var endpoints = this.endpoints || [];
      endpoints.push('deliver_component'); // all Netzke components get this endpoint
      Ext.each(endpoints, function(intp){
        this[intp.camelize(true)] = function(args, callback, scope){ this.callServer(intp, args, callback, scope); }
      }, this);
    },

    /*
    Detects component placeholders in the passed object (typically, "items"),
    and merges them with the corresponding config from this.components.
    This way it becomes ready to be instantiated properly by Ext.
    */
    detectComponents: function(o){
      if (Ext.isObject(o)) {
        if (o.items) this.detectComponents(o.items);
      } else if (Ext.isArray(o)) {
        var a = o;
        Ext.each(a, function(el, i){
          if (el.component) {
            a[i] = Ext.apply(this.components[el.component.camelize(true)], el);
            delete a[i].component;
          } else if (el.items) this.detectComponents(el.items);
        }, this);
      }
    },

    /*
    Evaluates CSS
    */
    evalCss : function(code){
      var linkTag = document.createElement('style');
      linkTag.type = 'text/css';
      linkTag.innerHTML = code;
      document.body.appendChild(linkTag);
    },

    /*
    Evaluates JS
    */
    evalJs : function(code){
      eval(code);
    },

    /*
    Gets id in the context of provided parent.
    For example, the components "properties", being a child of "books" has global id "books__properties",
    which *is* its widegt's real id. This methods, with the instance of "books" passed as parameter,
    returns "properties".
    */
    localId : function(parent){
      return this.id.replace(parent.id + "__", "");
    },

    /*
    Executes a bunch of methods. This method is called almost every time a communication to the server takes place.
    Thus the server side of a component can provide any set of commands to its client side.
    Args:
      - instructions: array of methods, in the order of execution.
        Each item is an object in one of the following 2 formats:
          1) {method1:args1, method2:args2}, where methodN is a name of a public method of this component; these methods are called in no particular order
          2) {component:component_id, methods:arrayOfMethods}, used for recursive call to bulkExecute on some child component

    Example:
      - [
          // the same as this.feedback("Your order is accepted")
          {feedback: "You order is accepted"},

          // the same as this.getChildComponent('users').bulkExecute([{setTitle:'Suprise!'}, {setDisabled:true}])
          {component:'users', methods:[{setTitle:'Suprise!'}, {setDisabled:true}] },

          // ... etc:
          {updateStore:{records:[[1, 'Name1'],[2, 'Name2']], total:10}},
          {setColums:[{},{}]},
          {setMenus:[{},{}]},
          ...
        ]
    */
    bulkExecute : function(instructions){
      if (Ext.isArray(instructions)) {
        Ext.each(instructions, function(instruction){ this.bulkExecute(instruction)}, this);
      } else {
        for (var instr in instructions) {
          if (Ext.isFunction(this[instr])) {
            // Executing the method. If arguments are an array, expand that into arguments.
            this[instr].apply(this, Ext.isArray(instructions[instr]) ? instructions[instr] : [instructions[instr]]);
          } else {
            var childComponent = this.getChildComponent(instr);
            if (childComponent) {
              childComponent.bulkExecute(instructions[instr]);
            } else {
              throw "Netzke: Unknown method or child component '" + instr +"' in component '" + this.id + "'"
            }
          }
        }
      }
    },

    // Returns API url based on provided API point
    buildApiUrl: function(endpoint){
      Netzke.deprecationWarning("buildApiUrl() is deprecated. Use endpointUrl() instead.");
      return this.endpointUrl(endpoint);
    },

    endpointUrl: function(endpoint){
      return Netzke.RelativeUrlRoot + "/netzke/" + this.id + "__" + endpoint;
    },

    // Does the call to the server and processes the response
    callServer : function(intp, params, callback, scope){
      Netzke.runningRequests++;
      if (!params) params = {};
        Ext.Ajax.request({
        params: params,
        url: this.endpointUrl(intp),
        callback: function(options, success, response){
          if (success && response.responseText) {
            // execute commands from server
            this.bulkExecute(Ext.decode(response.responseText));

            // provide callback if needed
            if (typeof callback == 'function') {
              if (!scope) scope = this;
              callback.apply(scope, [this.latestResult]);
            }
          }
        },
        scope : this
      });
      Netzke.runningRequests--;
    },

    setResult: function(result) {
      this.latestResult = result;
    }
  }, Netzke.classes.Core.Mixin);
};

// Netzke extensions for Ext.Container
Ext.override(Ext.Container, {
  // Instantiates an component by its config. If it appears to be a window, shows it instead of adding as item.
  // TODO: there must be a method to just instantiate a component, but not to add/show it instantly.
  instantiateChild : function(config){
    var instance = Ext.create(config);
    if (instance.isXType("window")) {
      instance.show();
    } else {
      this.remove(this.getNetzkeComponent()); // first delete previous component
      this.add(instance);

      // Sometimes a child is getting loaded into a hidden container...
      if (this.isVisible()) {
        this.doLayout();
      } else {
        this.on('show', function(cmp){cmp.doLayout();}, {single: true});
      }

    }
    return instance;
  },

  /**
    Get Netzke component that this Ext.Container is part of (*not* the parent component, for which call getParent)
    It searches up the Ext.Container hierarchy until it finds a Container that has isNetzke property set to true
    (or until it reaches the top).
  */
  getOwnerComponent : function(){
    if (this.initialConfig.isNetzke) {
      return this;
    } else {
      if (this.ownerCt){
        return this.ownerCt.getOwnerComponent()
      } else {
        return null
      }
    }
  },

  // Get the component that we are hosting
  getNetzkeComponent: function(){
    return this.items ? this.items.first() : null; // need this check in case when the container is not yet rendered, like an inactive tab in the TabPanel
  },

  // Remove the child
  removeChild : function(){
    this.remove(this.getNetzkeComponent());
  }
});

// Feedback Ghost
Netzke.FeedbackGhost = function(){};
Ext.apply(Netzke.FeedbackGhost.prototype, {
  showFeedback: function(msg){
    var createBox = function(s, l){
        return ['
',
                '

',
                '

', s, '

',
                '

',
                '
'].join('');
    }

    var showBox = function(msg, lvl){
      if (!lvl) {lvl = 'notice'};

      var msgCt = Ext.get('netzke-feedback') || Ext.DomHelper.insertFirst(document.body, {id: 'netzke-feedback', 'class':'netzke-feedback'}, true);

      var m = Ext.DomHelper.append(msgCt, {html:createBox(msg,lvl)}, true);
      m.slideIn('t').pause(2).ghost("b", {remove:true});
    }

    if (typeof msg != 'string') {
      var compoundMsg = "";
      Ext.each(msg, function(m){
        compoundMsg += m.msg + '
';
      });
      if (compoundMsg != "") showBox(compoundMsg, null); // the second parameter will be level
    } else {
      showBox(msg);
    }
  }
});
<|endoftext|>


<commit_before>/**
 * modalEffects.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2013, Codrops
 * http://www.codrops.com
 *
 * Modified by Mark Neuburger
 *
 */

import marked from 'marked'
import axios from 'axios'
import fm from 'front-matter'

var ModalEffects = (function () {
  function init () {
    var overlay = document.querySelector('.md-overlay');

    [].slice.call(document.querySelectorAll('.md-trigger')).forEach(function (el, i) {
      var modal = document.querySelector('#modal'),
        close = modal.querySelector('.md-close')

      function removeModalHandler () {
        classie.remove(modal, 'md-show')
      }

      el.addEventListener('click', function (ev) {
        ev.preventDefault()
        classie.add(modal, 'md-show')
        overlay.removeEventListener('click', removeModalHandler)
        overlay.addEventListener('click', removeModalHandler)

        let filename = el.getAttribute('data-project')
        axios.get(`/projects/${filename}.md`)
          .then((response) => {
            let projectData = fm(response.data)
            modal.querySelector('.title').innerHTML = projectData.attributes.title + ' ' + projectData.attributes.year + ''
            modal.querySelector('.scroll-content').innerHTML = marked(projectData.body)
          })
      })

      close.addEventListener('click', function (ev) {
        ev.stopPropagation()
        removeModalHandler()
      })
    })
  }

  init()
})()
<commit_msg>Add esc key to close on modal<commit_after>/**
 * modalEffects.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2013, Codrops
 * http://www.codrops.com
 *
 * Modified by Mark Neuburger
 *
 */

import marked from 'marked'
import axios from 'axios'
import fm from 'front-matter'

var ModalEffects = (function () {
  function init () {
    var overlay = document.querySelector('.md-overlay');

    [].slice.call(document.querySelectorAll('.md-trigger')).forEach(function (el, i) {
      var modal = document.querySelector('#modal'),
        close = modal.querySelector('.md-close')

      function removeModalHandler () {
        classie.remove(modal, 'md-show')
      }

      el.addEventListener('click', function (ev) {
        ev.preventDefault()
        classie.add(modal, 'md-show')
        overlay.removeEventListener('click', removeModalHandler)
        overlay.addEventListener('click', removeModalHandler)

        let filename = el.getAttribute('data-project')
        axios.get(`/projects/${filename}.md`)
          .then((response) => {
            let projectData = fm(response.data)
            modal.querySelector('.title').innerHTML = projectData.attributes.title + ' ' + projectData.attributes.year + ''
            modal.querySelector('.scroll-content').innerHTML = marked(projectData.body)
          })
      })

      document.onkeydown = function (e) {
        e = e || window.event
        if (e.keyCode == 27) {
          e.stopPropagation()
          removeModalHandler()
        }
      }

      close.addEventListener('click', function (ev) {
        ev.stopPropagation()
        removeModalHandler()
      })
    })
  }

  init()
})()
<|endoftext|>


<commit_before>var EC = protractor.ExpectedConditions;

fdescribe('con10t-image', function() {

    fit('should display an image from a given url', function() {
        browser.get('/project/steindorff');
        var marker = element(by.css('.con10t-image-fromsrc'));
        browser.wait(EC.presenceOf(marker), 10000);
        expect(marker.isPresent()).toBe(true);
    });

    it('should display an image from an arachne entity identifier', function() {
        browser.get('/project/schlossfulda');
        var marker = element(by.css('.con10t-image-fromentityid'));
        browser.wait(EC.presenceOf(marker), 10000);
        expect(marker.isPresent()).toBe(true);
    });

});

<commit_msg>Update con10t.spec.js<commit_after>var EC = protractor.ExpectedConditions;

describe('con10t-image', function() {

    it('should display an image from a given url', function() {
        browser.get('/project/steindorff');
        var marker = element(by.css('.con10t-image-fromsrc'));
        browser.wait(EC.presenceOf(marker), 10000);
        expect(marker.isPresent()).toBe(true);
    });

    it('should display an image from an arachne entity identifier', function() {
        browser.get('/project/schlossfulda');
        var marker = element(by.css('.con10t-image-fromentityid'));
        browser.wait(EC.presenceOf(marker), 10000);
        expect(marker.isPresent()).toBe(true);
    });

});

<|endoftext|>


<commit_before>
<commit_msg>[HOME] add carousel-control with key<commit_after>
/*
  key-control for carousel
*/
$(document).on('keyup', function(e) {
    if(e.which == 39){
        $('.carousel').carousel('next');
    }
    else if(e.which == 37){
        $('.carousel').carousel('prev');
    }
});
<|endoftext|>