📄 sectionstack.js
字号:
// List of sectionIDs // @param [callback] callback to fire when the section has been hidden // // @see sectionStack.collapseSection // @visibility external // @example sectionsShowAndHide //< hideSection : function (sections, callback) { this._hideSection(sections, true, false, callback); }, //> @method sectionStack.collapseSection() // // Collapse a section or sections. This action hides all the items assigned to the // section. Calling this method is equivalent to the user clicking on the SectionHeader of // an expanded section. // // @param sections (position|sectionId|list of sectionIDs) // Section(s) to collapse. For this parameter, you can pass the position // of the section in the SectionStack, the ID of the section, or a // List of sectionIDs // // @param [callback] callback to fire when the section has been collapsed // @see sectionStack.hideSection // @visibility external // @example sectionsExpandCollapse //< collapseSection : function (sections, callback) { this._hideSection(sections, false, true, callback); }, _hideSection : function (sections, hideSection, collapseSection, callback) { if (!isc.isAn.Array(sections)) sections = [sections]; var itemsToHide = []; for (var i = 0; i < sections.length; i++) { var section = this.getSectionHeader(sections[i]); // bad section specification if (section == null) { this.logWarn("no such section: " + this.echo(section)); continue; } if (hideSection && !section.hidden) { section.hidden = true; itemsToHide.add(section); } if (collapseSection || section.expanded) { // Backcompat: setOpen is deprecated, but we still want to call it if there's a // backcompat definition. Otoh it's possible that we just have setExpanded, so try // that first and then call setOpen if (collapseSection) { if (section.setExpanded && !section.setOpen) section.setExpanded(false); else if (section.setOpen) section.setOpen(false); } // some items may not have yet been added as members, so don't try to hide() // those or we'll crash in Layout if (section.items) { for (var j = 0; j < section.items.length; j++) { if (this.members.contains(section.items[j])) itemsToHide.add(section.items[j]); } } } } // forceFill: override recent user resizes to fill available space. NOTE: don't // forceFill if we're overflowed, as this would shrink us further after a collapse, // which is unexpected (this feature should be moved up to Layout as an optional // reaction to a hide) if (this.forceFill && this.getVisibleHeight() <= this.getHeight()) { // we want to make sure that some section(s) expand to fill the space vacated by this // hide/collapse. We scan through the members array to see if one of the items // will be resized by the layout automatically. If not, we pick one to forcibly // resize to fill the vacated space. // We're going to scan back from the first sectionHeader and then forward to try to // find an auto-resizable member and at the same time, we'll flag one that we can // forcefully resize if no auto-resizeable members are found. var startIndex = this.getMemberNumber(this.getSectionHeader(sections[0])); var forceResizeTarget; var layoutWillReflow = false; // scan back for (var i = startIndex-1; i >= 0; i--) { var member = this.members[i]; if (itemsToHide.contains(member)) continue; if (this.memberIsDragResizeable(member)) { if (this.memberHasAutoResizeableHeight(member)) { layoutWillReflow = true; break; } else if (forceResizeTarget == null) { forceResizeTarget = member; } } } if (!layoutWillReflow) { // scan forward for (var i = startIndex+1; i < this.members.length; i++) { var member = this.members[i]; if (itemsToHide.contains(member)) continue; if (this.memberIsDragResizeable(member)) { if (this.memberHasAutoResizeableHeight(member)) { layoutWillReflow = true; break; } else if (forceResizeTarget == null) { forceResizeTarget = member; } } } } if (!layoutWillReflow && forceResizeTarget != null) {// this.logWarn("layout will not reflow, forceResizing: " + forceResizeTarget.ID); forceResizeTarget._userHeight = null;// } else {// if (layoutWillReflow) this.logWarn("layout will reflow");// else this.logWarn("layout will not reflow and no forceResizeTarget"); } } this.hideMembers(itemsToHide, callback); }, //> @method sectionStack.sectionIsVisible() // // Returns true if the specified section is visible, false if it is not. A section is // visible if it shows a header and the header is visible or if it has items and the first // item is visible. // // @param section (sectionId|position) // Section for which you want to obtain visibility information. // For this parameter, you can pass the position of the section in the // SectionStack, or the ID of the section. // // @return (boolean) true if the section is visible, false if it is not. // // @visibility external //< sectionIsVisible : function (section) { section = this.getSectionHeader(section); if (section.showHeader && section.isVisible()) return true; // NOTE: have to consider lazy initialization case var sectionMember = section.items.first(); if (sectionMember == null || !isc.isA.Canvas(sectionMember) || !sectionMember.isDrawn() || sectionMember.visibility == isc.Canvas.HIDDEN) return false; return true; }, //> @method sectionStack.getVisibleSections() // // Returns the list of currently visible sections. The list items are section IDs. // // @return (List) list of hidden sections // // @visibility external //< getVisibleSections : function() { var visibleSections = []; for (var i = 0; i < this.sections.length; i++) if (this.sectionIsVisible(this.sections[i])) visibleSections.add(this.sections[i].ID); return visibleSections; }, //> @method sectionStack.sectionIsExpanded() // // Returns true if the specified section is expanded, false if it is collapsed. // // @param section (sectionId|position) // Section for which you want to obtain information. // For this parameter, you can pass the position of the section in the // SectionStack, or the ID of the section. // // @return (boolean) true if the section is expanded, false if it is not. // // @visibility external //< sectionIsExpanded : function (section) { return this.getSectionHeader(section).expanded; }, //> @method sectionStack.getExpandedSections() // // Returns the list of currently expanded sections. The list items are section IDs. // // @return (List) list of currently expanded sections // // @visibility external //< getExpandedSections : function () { var expandedSections = this.sections.findAll("expanded", true); return expandedSections == null ? [] : expandedSections.getProperty("_ID"); }, //> @method sectionStack.setSectionTitle() // Changes the title of a SectionHeader. // // @param section (String or Number) ID or index of the section whose title you want to change // @param newTitle (String) new title for the SectionHeader // @visibility external //< setSectionTitle : function (section, newTitle) { var sectionHeader = this.getSectionHeader(section); if (sectionHeader) sectionHeader.setTitle(newTitle); }, //> @method sectionStack.getSectionHeader() // Return the SectionHeader for a section. // <P> // This will be an instance of the +link{sectionHeaderClass}. Since different // SectionStacks may use different header classes, be careful about what APIs you rely on // for the section header unless you have explicitly set the // <code>sectionHeaderClass</code>. In particular, use APIs such as // +link{setSectionTitle()} to manipulate header indirectly wherever possible, as high // performance SectionStacks designed for very large numbers of sections may cache and // re-use headers or use other strategies that would make it invalid to store a pointer to // a section header, assumed the header is a layout member, etc. // // @param section (String or Number) ID or index of the section for which you want the header // @return (SectionHeader) the section header indicated // @visibility external //< getSectionHeader : function (section) { return isc.Class.getArrayItem(section, this.sections, "_ID"); }, getSection : function (section) { return this.getSectionHeader(section) }, //> @method sectionStack.getSectionNumber() // // Returns the position of the specified section in the SectionStack. The numbering is // zero-based. // // @param sectionID (string) ID of a section for which you want to obtain the position. // // @return (number) Position of the section in the SectionStack or -1 if the specified // section is not a member of this SectionStack. // // @visibility external //< getSectionNumber : function (section) { if (isc.isA.String(section)) { return this.sections.findIndex("_ID", section); // handle being passed a pointer to a section directly } else { return this.sections.indexOf(section); } }, // returns the position in the members array where the first item (header or first item in the // section.items array if showHeader = false) in this section should be // // for external interfaces we only care about the index of the section in this.sections, // because that's what all external methods take as a section identifier (among others) and // end users shouldn't be directly modifying the underlying Layout. _getSectionPosition : function (section) { // if the section header has already been added as a member, it's position is // straightforward. var headerPosition = this.getMemberNumber(section); if (headerPosition != -1) return headerPosition; // otherwise look for the position of the last item in the previous section var sectionIndex = this.sections.indexOf(section); // if we're the first section we start at zero if (sectionIndex <= 0) return sectionIndex; // otherwise we start after the last item of the preceding section var previousSection = this.sections[sectionIndex-1], lastMember = previousSection.items ? previousSection.items.last() : null; if (this.hasMember(lastMember)) { return this.getMemberNumber(lastMember) + 1; } else { // NOTE: sections without headers always have their items added immediately, since // there's no way to hide them return this.getMemberNumber(previousSection) + 1; } }, //> @method SectionStack.sectionHeaderClick (A) // Method intended to be called by the sectionHeader when it is clicked on. // // @param sectionHeader (Canvas) the sectionHeader clicked on // @visibility external //< sectionHeaderClick : function (section) { // hide the currently visible pane and show the pane for the header that got clicked on if (this.visibilityMode == "mutex") { if (this.sectionIsExpanded(section)) return false; // keep only one section visible: hide the currently visible section this.collapseSection(this._lastExpandedSection); // show the new section this.expandSection(section); } else { // just toggle expanded/collapsed if (!this.sectionIsExpanded(section)) { this.expandSection(section); } else { this.collapseSection(section); } } // remember this as the new last section this._lastExpandedSection = section; return false; // cancel event bubbling }, // For a given member, return the closest resizeable member _before_ us in the members // array. See memberIsResizeable() for what constitutes a resizeable member. getDragResizeTarget : function (member) { var myIndex = this.getMemberNumber(member); // look for a member preceding us that can be resized var resizeTarget; this._resizeIgnore = 0; for (var i = myIndex-1; i >= 0; i--) { var member = this.getMember(i); if (this.memberIsDragResizeable(member)) { resizeTarget = member; break; } // as we pass non-resizeable members, store up their total height, which we will // use as offset when using the coordinate of the dragged section header to resize
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -