특정 노드를 지정하는 재고의 방법은 없습니다 <splitter>
크기를 조정하십시오. XUL의 모든 크기 조정과 마찬가지로
는 의도 당신이 어떤없이 당신은 UI를 레이아웃, 또는 자동으로 <splitter>
요소를 사용하여 그것의 내부 부분의 크기를 조정할 수 있음을 당신의 XUL 등을 코딩 할 수 있어야한다는 것입니다 자바 스크립트가 이벤트를 듣고 크기 조정을 수행해야합니다. 그러나 JavaScript가 <splitter>
크기 조정을 수행하도록 할 수는 있습니다. 일반적으로 복잡한 작업을 수행하고 <splitter>
구현의 버그 중 하나에 부딪혔을 때 스톡 기능을 사용하도록 XUL을 미세 조정하는 것보다 쉽게 찾을 수 있습니다. 자신 만의 코드를 작성하는 완전한 컨트롤. 요점은 <splitter>
과 기본 시스템 은이 전체 크기 조정을 수행해야한다는 것입니다.
그러나, <splitter>
요소에는 중요한 제한 사항이 있으며, 몇 가지 버그가있어서 사용자 자신의 크기 조정 코드를 작성할 필요가 발생할 수 있습니다. 이러한 제한 사항은 다음과 같습니다.
flex
속성이 오버로드되었습니다. 객체를 처음에 배치하는 방법, 윈도우 크기를 조정할 때 크기를 조정하는 방법 및 모두 <splitters>
으로 크기를 조정하는 방법을 제어하는 데 사용됩니다. 각각의 경우에 서로 다른 일이 일어나길 바랄 수 있습니다.
<splitter>
코드에 버그가 있습니다. 필자는 유연하지 않은 것으로 명시 적으로 선언 된 요소가 여전히 크기가 조절되는 요소를 포함하여 적어도 두 가지 다른 요소를 관찰했습니다. IIRC의 경우 이러한 항목은 주로 컨테이너 내에있는 <splitter>
을 사용하여 해당 컨테이너의 개체 크기를 변경하려고 할 때 나타납니다.
<splitter>
의 크기를 조정할 요소를 명시 적으로 (예 : ID로) 지정할 수있는 기능이 없습니다.
는 [좀 더 제한에 대해 생각했다,하지만 난 그 순간에 그들을 기억하고 있지 않다.]
당신이 당신의 자신의 처리를 할 자바 스크립트를 사용하려는 경우, 당신이를 구현해야합니다 나타납니다 기능을 완전히 듣고 mouse events. <splitter>
의 움직임은 drag events 발생하지 않습니다.<splitter>
이동은 '드래그 앤 드롭'작업의 일부로 간주되지 않으므로 (즉, 실제로 가져 와서 드롭 대상에 드롭하지 않기 때문) 나는 드래그 이벤트를들을 수있을 것으로 예상했지만, 그들이 발사하지 않는다는 것이 분명합니다.
나를 위해, <splitters>
에서 부족한 가장 중요한 기능은 크기를 조정할 두 요소를 ID로 지정하는 기능이 부족하다는 것입니다. 분명히, 귀하의 질문의 제목에서, 이것은 또한 당신이 크게 부족한 것으로 판명 뭔가 분명하다.
<splitter>
에 ID를 지정하는 추가 : 요소의 ID를 지정
다음 코드가 구현 및 이용의 예시를 제공 <splitter>
요소는 XUL 내의 resizebefore
및 resizeafter
특성으로 조정할 수 .
특정 <splitter>
에 사용하기 위해, 당신은 <splitter>
의 ID 또는 <splitter>
요소 중 하나를 사용하여 <splitter>
를 등록하는 공공 기능 중 하나를 호출해야합니다. 에서 수정 (
/******************************************************************************
* splitterById *
* *
* XUL <splitter> elements which are registered will resize only the two *
* specific elements for which the ID is contained in the <splitter>'s *
* resizebefore and resizeafter attributes. The orient attribute is used to *
* specify if the <splitter> is resizing in the "vertical" or "horizontal" *
* orientation. "vertical" is the default. *
* *
* For a particular <splitter> this is an all or nothing choice. In other *
* words, you _must_ specify both a before and after element (e.g. You can not *
* mix using an ID on the resizebefore and not on resizeafter with the *
* expectation that the after will be resized with the normal <splitter> *
* functionality. *
* *
* On both elements, the attributes minheight, maxheight, minwidth, and *
* maxwidth will be obeyed. It may be necessary to explicitly set these *
* attributes in order to prevent one or the other element from growing or *
* shrinking when the other element is prevented from changing size by other *
* XUL UI constraints. For example, an element can not be reduced in size *
* beyond the minimum needed to display it. This code does not check for these *
* other constraints. Thus, setting these attributes, at least the ones *
* specifying the minimum height or minimum width will almost always be *
* desirable. *
* *
* Public methods: *
* registerSplitterById(id) : registers the <splitter> with that ID *
* registerSplitterByElement(element) : registers the <splitter> element *
* unregisterSplitterById(id) : unregisters the <splitter> with that ID *
* unregisterSplitterByElement(element) : unregisters the <splitter> element *
* *
******************************************************************************/
var splitterById = (function(){
let beforeER = {};
let afterER = {};
let splitIsVertical = true;
let origClientY = -1;
let origClientX = -1;
function ElementRec(_el) {
this.element = _el;
this.origHeight = getElementHeight(_el);
this.origWidth = getElementWidth(_el);
//The .minHeight and .maxHeight attributes/properties
// do not appear to be valid when first starting, so don't
// get them here.
//this.minHeight = getMinHeightAsValue(_el);
//this.maxHeight = getMaxHeightAsValue(_el);
}
function getElementHeight(el) {
//.height can be invalid and does not indicate the actual
// height displayed, only the desired height.
let boundingRec = el.getBoundingClientRect();
return boundingRec.bottom - boundingRec.top;
}
function getElementWidth(el) {
//.width can be invalid and does not indicate the actual
// width displayed, only the desired width.
let boundingRec = el.getBoundingClientRect();
return boundingRec.right - boundingRec.left;
}
function getMaxHeightAsValue(el) {
return asValueWithDefault(el.maxHeight,99999999);
}
function getMinHeightAsValue(el) {
return asValueWithDefault(el.minHeight,0);
}
function getMaxWidthAsValue(el) {
return asValueWithDefault(el.maxHeight,99999999);
}
function getMinWidthAsValue(el) {
return asValueWithDefault(el.minHeight,0);
}
function asValueWithDefault(value,myDefault) {
if(value === null || value === "" || value === undefined) {
value = myDefault;
}
//What is returned by the various attributes/properties is
// usually text, but not always.
value++;
value--;
return value;
}
function storeSplitterStartingValues(el) {
//Remember if the splitter is vertical or horizontal,
// references to the elements being resized and their initial sizes.
splitIsVertical = true;
if(el.getAttribute("orient") === "horizontal") {
splitIsVertical = false;
}
beforeER=new ElementRec(document.getElementById(el.getAttribute("resizebefore")));
afterER=new ElementRec(document.getElementById(el.getAttribute("resizeafter")));
if(beforeER.element === undefined || afterER.element === undefined) {
//Did not find one or the other element. We must have both.
return false;
}
return true;
}
function mousedownOnSplitter(event) {
if(event.button != 0) {
//Only drag with the left button.
return;
}
//Remember the mouse position at the start of the resize.
origClientY = event.clientY;
origClientX = event.clientX;
//Remember what we are acting upon
if(storeSplitterStartingValues(event.target)) {
//Start listening to mousemove and mouse up events on the whole document.
document.addEventListener("mousemove",resizeSplitter,true);
document.addEventListener("mouseup",endResizeSplitter,true);
}
}
function endResizeSplitter(event) {
if(event.button != 0) {
//Only drag with the left button.
return;
}
removeResizeListeners();
}
function removeResizeListeners() {
//Don't listen to document mousemove, mouseup events when not
// actively resizing.
document.removeEventListener("mousemove",resizeSplitter,true);
document.removeEventListener("mouseup",endResizeSplitter,true);
}
function resizeSplitter(event) {
//Prevent the splitter from acting normally:
event.preventDefault();
event.stopPropagation();
//Get the new size for the before and after elements based on the
// mouse position relative to where it was when the mousedown event fired.
let newBeforeSize = -1;
let newAfterSize = -1;
if(splitIsVertical) {
newBeforeSize = beforeER.origHeight + (event.clientY - origClientY);
newAfterSize = afterER.origHeight - (event.clientY - origClientY);
} else {
newBeforeSize = beforeER.origWidth + (event.clientX - origClientX);
newAfterSize = afterER.origWidth - (event.clientX - origClientX);
}
//Get any maximum and minimum sizes defined for the elements we are changing.
//Get these here because they may not have been populated/valid
// when the drag was first initiated (i.e. we should have been able
// to do this only once when the mousedown event fired, but testing showed
// the values are not necessarily valid at that time.
let beforeMinSize;
let beforeMaxSize;
let afterMinSize;
let afterMaxSize;
if(splitIsVertical) {
beforeMinSize = getMinHeightAsValue(beforeER.element);
beforeMaxSize = getMaxHeightAsValue(beforeER.element);
afterMinSize = getMinHeightAsValue(afterER.element);
afterMaxSize = getMaxHeightAsValue(afterER.element);
} else {
beforeMinSize = getMinWidthAsValue(beforeER.element);
beforeMaxSize = getMaxWidthAsValue(beforeER.element);
afterMinSize = getMinWidthAsValue(afterER.element);
afterMaxSize = getMaxWidthAsValue(afterER.element);
}
//Apply the limits to sizes we want to change to.
//These do appear to work better sequentially rather than optimized.
if(newBeforeSize < beforeMinSize) {
//Set to beforeMinSize limit if have passed.
let diff = beforeMinSize - newBeforeSize;
newBeforeSize += diff;
newAfterSize -= diff;
}
if(newBeforeSize > beforeMaxSize) {
//Set to beforeMaxSize limit if have passed.
let diff = beforeMaxSize - newBeforeSize;
newBeforeSize += diff;
newAfterSize -= diff;
}
if(newAfterSize < afterMinSize) {
//Set to afterMinSize limit if have passed.
let diff = afterMinSize - newAfterSize;
newAfterSize += diff;
newBeforeSize -= diff;
}
if(newAfterSize > afterMaxSize) {
//Set to afterMaxSize limit if have passed.
let diff = afterMaxSize - newAfterSize;
newAfterSize += diff;
newBeforeSize -= diff;
}
//Don't make any changes if we are still violating the limits.
//There are some pathological cases where we could still be violating
// a limit (where limits are set such that it is not possible to have
// a valid height).
if(newBeforeSize < beforeMinSize || newBeforeSize > beforeMaxSize
|| newAfterSize < afterMinSize || newAfterSize > afterMaxSize) {
return;
}
//Make the size changes
if(splitIsVertical) {
beforeER.element.height = newBeforeSize;
afterER.element.height = newAfterSize;
} else {
beforeER.element.width = newBeforeSize;
afterER.element.width = newAfterSize;
}
}
function _registerSplitterById(id) {
_registerSplitterByElement(document.getElementById(id));
}
function _registerSplitterByElement(el) {
el.addEventListener("mousedown",mousedownOnSplitter,false);
}
function _unregisterSplitterById(id) {
_unregisterSplitterByElement(document.getElementById(id));
}
function _unregisterSplitterByElement(el) {
el.removeEventListener("mousedown",mousedownOnSplitter,false);
removeResizeListeners();
}
return {
registerSplitterById : function(id) {
_registerSplitterById(id);
},
registerSplitterByElement : function(el) {
_registerSplitterByElement(el);
},
unregisterSplitterById : function(id) {
_unregisterSplitterById(id);
},
unregisterSplitterByElement : function(el) {
_unregisterSplitterByElement(el);
}
};
})();
예 XUL :
splitterById.registerSplitterById("firstSplitter");
splitterById.registerSplitterById("secondSplitter");
splitterById.js 예를 들어, (약간 질문의 코드에서 수정) 예 XUL에있는 두 <spliter>
요소에 등록 질문) :
:
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="testWindow"
title="testing resizing element by splitter"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="color: white;"
>
<vbox id="resizeme" height="120" minheight="30" maxheight="250"
style="background-color: yellow; color: black;">
<hbox flex="1">
<label value="#1"/>
<hbox flex="1" align="center" pack="center">
<label id="yellowLabel" value="Resizable by top and bottom splitter"/>
</hbox>
</hbox>
</vbox>
<splitter id="firstSplitter" tooltiptext="Top splitter" orient="vertical"
resizebefore="resizeme" resizeafter="blueVbox"/>
<grid>
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row style="background-color: black;">
<label value="#2"/>
<vbox pack="center" align="center">
<label value="Must stay constant size at all times"/>
</vbox>
</row>
<row id="blueRow" style="background-color: blue;">
<label value="#3"/>
<vbox id="blueVbox" height="120" minheight="30" pack="center" align="center">
<label id="blueLabel" value="Resizable by top splitter only"/>
</vbox>
</row>
<row style="background-color: black;">
<label value="#4"/>
<hbox pack="center" align="center">
<label value="Must stay constant size at all times, content must fit"/>
<button label="blah"/>
</hbox>
</row>
<splitter id="secondSplitter" tooltiptext="Bottom splitter" orient="vertical"
resizebefore="resizeme" resizeafter="greenVbox"/>
<row id="greenRow" style="background-color: green;">
<label value="#5"/>
<vbox id="greenVbox" height="120" minheight="30" pack="center" align="center">
<label id="greenLabel" value="Resizable by bottom splitter only"/>
</vbox>
</row>
<row style="background-color: black;">
<label value="#6"/>
<vbox pack="center" align="center">
<label value="Must stay constant size at all times"/>
</vbox>
</row>
</rows>
</grid>
<script type="application/x-javascript" src="file://b:/SplitterById.js"/>
<script type="application/javascript">
<![CDATA[
splitterById.registerSplitterById("firstSplitter");
splitterById.registerSplitterById("secondSplitter");
]]>
</script>
</window>
이 예처럼 보인다
[참고 : 코드가 수직 및 <splitters>
수평 모두 작동하도록 작성하는 동안, 난 단지 위의 예에서 수직 <splitters>
와 함께 테스트했습니다.]
을 이벤트를 수신하지 않고 (일반적으로 <splitter>
사용) :
처음 질문에 사용한 예는 현재 가지고있는 예보다 훨씬 덜 복잡합니다. XUL을 엄격하게 사용하여 코드를 작성하여 <splitter>
이 요청한 방식대로 작동하도록 할 수있었습니다.
<splitter>
요소를 통해 크기 조정되는 개체 또는 전체 레이아웃의 일반적인 크기 조정을 제어하는 데 사용할 수있는 여러 가지 방법 (여러 가지 조합이 다양하게 조합되어 있음)이 있습니다. 무엇보다도,이는 XUL의 요소에 flex
속성에 대한 적절한 값으로 조합하여 <splitter>
의 resizebefore
및 resizeafter
속성을 사용하고 잠재적를 배포하는 데에만 사용됩니다 그 box
요소, hbox
, 또는 vbox
요소를 포함 포함 "굽힘". 또한 다양한 attributes available to an XUL element (추가 MDN 문서 : 1, 2, 3)을 사용하여 크기를 조정할 영역 내의 각 요소에 대한 다양한 제한을 지정하는 것이 바람직 할 수 있습니다. 당신이 놓친 나타나는 것들의
하나는 flex
속성이 단지 1
또는 0
이외의 값이 될 수 있다는 것입니다.숫자 값은 크기 조정의 영향을받는 다른 요소를 기준으로 특정 요소에서 수행되는 크기 조정의 양을 비례 적으로 지정하는 데 사용됩니다 (<splitter>
또는 컨테이너 요소의 크기 조정 (예 : <window>
, <box>
, <vbox>
, <hbox>
등)에 관심이있는 요소가 포함되어 있습니다.
시행 착오 :
을 얻으려면 정확히 특정 레이아웃에서 원하는 기능을 당신은 아마 약간의 시행 착오를 수행해야합니다. XUL 프로토 타이핑 도구 XUL Explorer은 수행중인 작업에 따라 그렇게하는 데 도움이 될 수 있습니다. 예를 들어, 코드가 동적으로 XUL을 빌드하면 XUL Explorer는별로 도움이되지 않습니다. 그러나, XUL 레이아웃을 동적으로 구축 할 때도 XUL Explorer를 사용하여 XUL의 변형이 어떻게 보이고/행동하는지 신속하게 확인했습니다.
내 (일본어) 구체 예 :
[참고 : 다음 질문에 포함 된 첫 번째 예에 근거한다. 이 예는 현재 질문에있는 것보다 훨씬 덜 복잡합니다. 특히, 그 용기의 외부 요소의 크기를 조정하도록 요구 한 컨테이너 (새로운 예에서 <grid>
) 내부 <splitter>
이 없었습니다.] 구체적인 예를 들어
, 당신이 설명하는 동작에 의해 달성 될 수있다 녹색의 flex
값을 다른 요소에 비해 큰 값으로 설정하십시오.
많은 UI 문제와 마찬가지로 발생하는 모든 것을 단어로 말하기는 어렵습니다. 예를 들어,이 경우 다른 <vbox>
요소의 시작 크기를 지정하지 않았습니다. <splitter>
에 대해 더 많은 것을 표시하고 flex
에 다른 값을 사용하면 녹색 <vbox>
이 표시되고 다른 <vbox>
요소에는 시작/기본값 height
이 포함되었습니다. 이렇게하면 해당 높이에서 시작하여 녹색에서 최소 높이로 수축 한 후 최소 높이까지만 줄어드는 요소가 생성됩니다.
참고 : 속성의 일부는 min-height: 30px;
입니다. 이것을 CSS 클래스에 넣지 않는 한, XUL 속성 minheight
을 사용하는 것이 더 쉽고/더 쉬울 수도 있습니다. 그렇게하면 프로그래밍 방식으로 변경하는 것이 더 쉬울 것이므로 원하는대로해야합니다. 이것이 예제 코드라는 것을 감안할 때, CSS 파일을 포함 할 필요가 없도록 바로 잡을 수 있습니다.
코드 : 그것은 크기를 조정하려면 <splitter>
를 사용할 때처럼 보이는 무엇
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="testWindow"
title="testing resizing element by splitter"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
<hbox flex="1">
<vbox flex="1">
<vbox flex="1" height="80" pack="center" align="center"
style="background-color: blue; min-height: 30px; color: white;">
<label value="this should stay constant size until green element reached its minimum size"/>
</vbox>
<vbox id="resizeme" flex="10000" height="80" pack="center" align="center"
style="background-color: green; min-height: 30px; color: white;">
<label value="only this should be resized until it reached minimum size of 30px"/>
</vbox>
<vbox flex="1" height="80" pack="center" align="center"
style="background-color: red; min-height: 30px; color: white;">
<label value="this should stay constant size until green element reached its minimum size"/>
</vbox>
</vbox>
</hbox>
<splitter/>
<vbox flex="1"/>
</window>
는 :
확인
, 예를 추가했습니다. – vanowm
내 잘못, 두 예를 모두 섞어서 ... 지금 고쳐 썼다. 두 분배기는 모두 노란색 상자의 크기를 조정해야하지만 상단 분배기는 파란색 행에만 영향을주고 하단 분배기는 녹색 행에만 영향을 주어야합니다. 사이드 노트는 xul 파일을 열고 하단 스플리터를 위로 움직이면 아래로 점프하여 예기치 않게 검은 색 # 4 행의 크기를 조정하면 이상한 동작이 발생합니다. – vanowm