根据另一个元素的宽度调整元素的宽度

时间:2017-07-25 16:54:57

标签: html css dynamic width

请在此处查看解决方案:

https://stackoverflow.com/a/41686102/4180447

上述解决方案可用于在Angular中实现可编辑的下拉列表(select)元素。但是,假设元素的宽度是固定的。现在,我们正在实现响应式设计,我需要一种方法来根据另一个元素的宽度调整元素的宽度。

基本上,实现使用两个元素并将它们放在彼此之上。一个元素是ID以_sel结尾的select元素,另一个元素是ID以_disp结尾的文本元素。文本元素必须比下拉元素窄,以便下拉箭头可见。

文本元素的宽度必须比select元素的宽度小约18px。

有没有办法调整文本输入的高度比select元素的大小小18px?

请参阅下面的快照和相关代码以澄清情况:

enter image description here

HTML:

<div class="select-editable stop-wrap" style="width: 265px; border:none">
    <select type="text" id="exterior_finish_sel" editable-dropdown="exterior_finish" name="exterior_finish_sel"
    ng-model="exterior_finish_sel" ng-options="o as o for o in ddlOptions.exterior_finish track by o" maxlength="80"
    class="ng-valid ng-valid-maxlength ng-not-empty ng-dirty ng-valid-parse ng-touched" style="">
    </select> 
    <input type="text" id="exterior_finish_disp" name="exterior_finish_disp" ng-model="exterior_finish_disp" style="width: 247px;"/> 
    <input type="text" id="exterior_finish" name="exterior_finish" ng-model="exterior_finish" ng-hide="true"/>
</div>

CSS:

.stop-wrap {
    display: inline-block;
}

.select-editable {
    position:relative;
    background-color:white;
    border:solid grey 1px;
    width:120px;
    height:25px;
    vertical-align: middle;
    margin-bottom: 5px;
}
.select-editable select {
    position:absolute;
    top:0px;
    left:0px;
    border:none;
    width:118px;
    margin:0;
}
.select-editable input {
    position:absolute;
    top:0px;
    left:0px;
    width:100px;
    padding:1px;
    border:none;
}
.select-editable select:focus, .select-editable input:focus {
    outline:none;
}

1 个答案:

答案 0 :(得分:0)

我在这里找到了基于解决方案的答案:

https://stackoverflow.com/a/18743145/4180447

将监视宽度/位置变化的jQuery插件:

jQuery.fn.onPositionChanged = function (trigger, millis) {
    if (millis == null) millis = 100;
    var o = $(this[0]); // our jquery object
    if (o.length < 1) return o;
    var lastPos = null;
    var lastOff = null;
    var lastWidth = null;
    var lastOffWidth = null;
    setInterval(function () {
        if (o == null || o.length < 1) return o; // abort if element is non existend eny more
        if (lastPos == null) lastPos = o.position();
        if (lastOff == null) lastOff = o.offset();
        if (lastWidth == null) lastWidth = o.width();
        if (lastOffWidth == null) lastOffWidth = o[0].offsetWidth;
        var newPos = o.position();
        var newOff = o.offset();
        var newWidth = o.width();
        var newOffWidth = o[0].offsetWidth;
        if (lastPos.top != newPos.top || lastPos.left != newPos.left) {
            $(this).trigger('onPositionChanged', { lastPos: lastPos, newPos: newPos });
            if (typeof (trigger) == "function") trigger(lastPos, newPos);
            lastPos = o.position();
        }
        if (lastOff.top != newOff.top || lastOff.left != newOff.left) {
            $(this).trigger('onPositionChanged', { lastOff: lastOff, newOff: newOff});
            if (typeof (trigger) == "function") trigger(lastOff, newOff);
            lastOff= o.offset();
        }
        if (lastWidth != newWidth) {
            $(this).trigger('onPositionChanged', { lastWidth: lastWidth, newWidth: newWidth});
            if (typeof (trigger) == "function") trigger(lastWidth, newWidth);
            lastWidth= o.width();
        }
        if (lastOffWidth != newOffWidth) {
            $(this).trigger('onPositionChanged', { lastOffWidth: lastOffWidth, newOffWidth: newOffWidth});
            if (typeof (trigger) == "function") trigger(lastOffWidth, newOffWidth);
            lastWidth= o.width();
        }
    }, millis);
    return o;
};

下面的editable-dropdown指令:

app.directive('editableDropdown', function ($timeout){
    return {
        link: function (scope, elemSel, attrs) {
            //This is the hidden input, and will be used for data binding
            var inpElemID = attrs.editableDropdown;
            var inpElem; 
            //This is the display element and will be used for showing the selected value
            var inpElemDispID = inpElemID + "_disp";
            var inpElemDisp;
            //The parameter 'elemSel' is the SELECT field
            function initInpElem() {
                //Get a reference to the hidden and displayed text field
                if ($(elemSel).is("select")) {
                    inpElem = $('#' + inpElemID);           //Hidden field
                    inpElemDisp = $('#' + inpElemDispID);   //Displayed field
                } else {
                    //This is in case the Dropdown is based on DATALIST which is not yet implemented
                    //In this case, the input element is actually the same as the dropdown field using DATALIST
                    inpElem = elemSel;
                }
            }
            initInpElem();
            function updateEditable(elm) {
                initInpElem();
                //Copy value from SELECT element to the INPUT Element
                //Use NgModelController to copy value in order to trigger validation for 'inpElem'
                var selectedValue = $(elm).children("option").filter(":selected").text();
                //Update the hidden text field which is used to save the value to DB
                angular.element(inpElem).controller('ngModel').$setViewValue(elm.val());
                angular.element(inpElem).controller('ngModel').$render();
                //Update the display text field based on the selection (text value)
                angular.element(inpElemDisp).controller('ngModel').$setViewValue($(elm).find('option:selected').text());
                angular.element(inpElemDisp).controller('ngModel').$render();
                makeEditable(elm);
            }
            function makeEditable(selElm) {
                //Allow edit text field if "other" is selected
                initInpElem();
                if ($(selElm).is("select")) {
                    //JIRA: NE-2995 - of option seletec starte with "other" then activate editable option
                    if (selElm.val().toLowerCase().startsWith("other")) {
                            //Make the display field editable
                          $(inpElemDisp).prop("readonly", false);
                    } else {
                            //Make the display field read-only
                          $(inpElemDisp).prop("readonly", true);
                    }
                } else {
                    if (elm.value != "Other" && !$(elm).attr("keypressOff")) {
                        $(elm).keypress(function(event) {
                            console.log("keypress preventd")
                            event.preventDefault();
                        })
                    } else {
                        $(elm).off("keypress");
                        $(elm).attr("keypressOff", true);
                        console.log("keypress event removed")
                    }
                }
            }
            function resizeElem() {
                angular.element(document).ready(function() {
                    initInpElem();
                    $(inpElemDisp).width($(elemSel).outerWidth()-20);
                })
            }
            angular.element(document).ready(function(){
                initInpElem();
                //When the display value changes, then update the hidden text field
                inpElemDisp.change(function(){
                    angular.element(inpElem).controller('ngModel').$setViewValue(inpElemDisp.val());
                    angular.element(inpElem).controller('ngModel').$render();               
                });
                makeEditable(elemSel);
            });
            //When field values are initialized, ensure the drop-down list and other fields are synchronized
            scope.$on('event:force-model-update', function() {
                initInpElem();
                //Use the value of the hidden field which is saved in DB to update the values of the other fields
                var selectedValue = $(elemSel).find('option[value="' + inpElem.val() + '"]').val();
                var selectedText;
                if (angular.isUndefined(selectedValue)) {
                    selectedText = inpElem.val();
                } else {
                    //Update the selected value
                    if (angular.element(elemSel).controller('ngModel')) {
                        angular.element(elemSel).controller('ngModel').$setViewValue(selectedValue);
                        angular.element(elemSel).controller('ngModel').$render();
                    }
                    $(elemSel).find('option[value="' + inpElem.val() + '"]').attr('selected', 'selected');
                    selectedText = $(elemSel).find('option:selected').text()
                }
                //Update the display value
                angular.element(inpElemDisp).controller('ngModel').$setViewValue(selectedText);
                angular.element(inpElemDisp).controller('ngModel').$render();
            });
            $(elemSel).change(function () {
                //Everytime the selected value is update, then change the display and hidden value
                updateEditable(elemSel);
            });
            $(elemSel).onPositionChanged(function() {
                resizeElem();
            })
        }
    }
});

上述代码需要改进才能监控仅对宽度的更改。我会在下一个冲刺中做到这一点。

塔雷克