ExtJS4 hbox layout issue - extjs

We are using ExtJS4 in our application.But we are facing an issue with hbox layout.We need to displat the items from right side.Normally in ExtJS4,items in hbox layout start from left side and move towards right side.But we need to start from right side and move towards left side.I think we need to change the order in ExtJS4 library(box layout).
ExtJS4 box layout is:
/*
This file is part of Ext JS 4
Copyright (c) 2011 Sencha Inc
Contact: http://www.sencha.com/contact
GNU General Public License Usage
This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
*/
Ext.define('Ext.layout.container.Box', {
alias: ['layout.box'],
extend: 'Ext.layout.container.Container',
alternateClassName: 'Ext.layout.BoxLayout'
requires: [
'Ext.layout.container.boxOverflow.None',
'Ext.layout.container.boxOverflow.Menu',
'Ext.layout.container.boxOverflow.Scroller',
'Ext.util.Format',
'Ext.dd.DragDropManager'
],
defaultMargins: {
top: 0,
right: 0,
bottom: 0,
left: 0
},
padding: '0',
type: 'box',
scrollOffset: 0,
itemCls: Ext.baseCSSPrefix + 'box-item',
targetCls: Ext.baseCSSPrefix + 'box-layout-ct',
innerCls: Ext.baseCSSPrefix + 'box-inner',
bindToOwnerCtContainer: true,
fixedLayout: false,
availableSpaceOffset: 0,
reserveOffset: true,
clearInnerCtOnLayout: false,
flexSortFn: function (a, b) {
var maxParallelPrefix = 'max' + this.parallelPrefixCap,
infiniteValue = Infinity;
a = a.component[maxParallelPrefix] || infiniteValue;
b = b.component[maxParallelPrefix] || infiniteValue;
// IE 6/7 Don't like Infinity - Infinity...
if (!isFinite(a) && !isFinite(b)) {
return false;
}
return a - b;
},
// Sort into *descending* order.
minSizeSortFn: function(a, b) {
return b.available - a.available;
},
constructor: function(config) {
var me = this;
me.callParent(arguments);
me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
me.initOverflowHandler();
},
getChildBox: function(child) {
child = child.el || this.owner.getComponent(child).el;
return {
left: child.getLeft(true),
top: child.getTop(true),
width: child.getWidth(),
height: child.getHeight()
};
},
calculateChildBox: function(child) {
var me = this,
boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
ln = boxes.length,
i = 0;
child = me.owner.getComponent(child);
for (; i < ln; i++) {
if (boxes[i].component === child) {
return boxes[i];
}
}
},
calculateChildBoxes: function(visibleItems, targetSize) {
var me = this,
math = Math,
mmax = math.max,
infiniteValue = Infinity,
undefinedValue,
parallelPrefix = me.parallelPrefix,
parallelPrefixCap = me.parallelPrefixCap,
perpendicularPrefix = me.perpendicularPrefix,
perpendicularPrefixCap = me.perpendicularPrefixCap,
parallelMinString = 'min' + parallelPrefixCap,
perpendicularMinString = 'min' + perpendicularPrefixCap,
perpendicularMaxString = 'max' + perpendicularPrefixCap,
parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
perpendicularSize = targetSize[perpendicularPrefix],
padding = me.padding,
parallelOffset = padding[me.parallelBefore],
paddingParallel = parallelOffset + padding[me.parallelAfter],
perpendicularOffset = padding[me.perpendicularLeftTop],
paddingPerpendicular = perpendicularOffset + padding[me.perpendicularRightBottom],
availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
isStart = me.pack == 'start',
isCenter = me.pack == 'center',
isEnd = me.pack == 'end',
constrain = Ext.Number.constrain,
visibleCount = visibleItems.length,
nonFlexSize = 0,
totalFlex = 0,
desiredSize = 0,
minimumSize = 0,
maxSize = 0,
boxes = [],
minSizes = [],
calculatedWidth,
i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall,
tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff,
flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset,
perpendicularMargins, stretchSize;
for (i = 0; i < visibleCount; i++) {
child = visibleItems[i];
childPerpendicular = child[perpendicularPrefix];
me.layoutItem(child);
childMargins = child.margins;
parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
tmpObj = {
component: child,
margins: childMargins
};
// flex and not 'auto' width
if (child.flex) {
totalFlex += child.flex;
childParallel = undefinedValue;
}
// Not flexed or 'auto' width or undefined width
else {
if (!(child[parallelPrefix] && childPerpendicular)) {
childSize = child.getSize();
}
childParallel = child[parallelPrefix] || childSize[parallelPrefix];
childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
}
nonFlexSize += parallelMargins + (childParallel || 0);
desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
// Max height for align - force layout of non-laid out subcontainers without a numeric height
if (typeof childPerpendicular != 'number') {
// Clear any static sizing and revert to flow so we can get a proper measurement
childPerpendicular = child['get' + perpendicularPrefixCap]();
}
// Track the maximum perpendicular size for use by the stretch and stretchmax align config values.
maxSize = mmax(maxSize, childPerpendicular + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
tmpObj[parallelPrefix] = childParallel || undefinedValue;
tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
boxes.push(tmpObj);
}
shortfall = desiredSize - parallelSize;
tooNarrow = minimumSize > parallelSize;
//the space available to the flexed items
availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
if (tooNarrow) {
for (i = 0; i < visibleCount; i++) {
box = boxes[i];
minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
box[parallelPrefix] = minSize;
}
}
else {
if (shortfall > 0) {
for (i = 0; i < visibleCount; i++) {
item = visibleItems[i];
minSize = item[parallelMinString] || 0;
if (item.flex) {
box = boxes[i];
box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
box[parallelPrefix] = minSize;
}
else {
minSizes.push({
minSize: minSize,
available: boxes[i][parallelPrefix] - minSize,
index: i
});
}
}
Ext.Array.sort(minSizes, me.minSizeSortFn);
for (i = 0, length = minSizes.length; i < length; i++) {
itemIndex = minSizes[i].index;
if (itemIndex == undefinedValue) {
continue;
}
item = visibleItems[itemIndex];
minSize = minSizes[i].minSize;
box = boxes[itemIndex];
oldSize = box[parallelPrefix];
newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
reduction = oldSize - newSize;
box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
box[parallelPrefix] = newSize;
shortfall -= reduction;
}
}
else {
remainingSpace = availableSpace;
remainingFlex = totalFlex;
flexedBoxes = [];
for (i = 0; i < visibleCount; i++) {
child = visibleItems[i];
if (isStart && child.flex) {
flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
}
}
Ext.Array.sort(flexedBoxes, me.flexSortFn);
for (i = 0; i < flexedBoxes.length; i++) {
calcs = flexedBoxes[i];
child = calcs.component;
childMargins = calcs.margins;
flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
remainingSpace -= flexedSize;
remainingFlex -= child.flex;
calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
calcs[parallelPrefix] = flexedSize;
}
}
}
if (isCenter) {
parallelOffset += availableSpace / 2;
}
else if (isEnd) {
parallelOffset += availableSpace;
}
if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
if (me.owner.frameSize) {
calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
}
availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
}
//finally, calculate the left and top position of each item
for (i = 0; i < visibleCount; i++) {
child = visibleItems[i];
calcs = boxes[i];
childMargins = calcs.margins;
perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
parallelOffset += childMargins[me.parallelBefore];
calcs[me.parallelBefore] = parallelOffset;
calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
if (me.align == 'stretch') {
stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
calcs[perpendicularPrefix] = stretchSize;
}
else if (me.align == 'stretchmax') {
stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
calcs[perpendicularPrefix] = stretchSize;
}
else if (me.align == me.alignCenteringString) {
// When calculating a centered position within the content box of the innerCt, the width of the borders must be subtracted from
// the size to yield the space available to center within.
// The updateInnerCtSize method explicitly adds the border widths to the set size of the innerCt.
diff = mmax(availPerpendicularSize, maxSize) - me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB) - calcs[perpendicularPrefix];
if (diff > 0) {
calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
}
}
// Advance past the box size and the "after" margin
parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
}
return {
boxes: boxes,
meta : {
calculatedWidth: calculatedWidth,
maxSize: maxSize,
nonFlexSize: nonFlexSize,
desiredSize: desiredSize,
minimumSize: minimumSize,
shortfall: shortfall,
tooNarrow: tooNarrow
}
};
},
onRemove: function(comp){
this.callParent(arguments);
if (this.overflowHandler) {
this.overflowHandler.onRemove(comp);
}
},
initOverflowHandler: function() {
var handler = this.overflowHandler;
if (typeof handler == 'string') {
handler = {
type: handler
};
}
var handlerType = 'None';
if (handler && handler.type !== undefined) {
handlerType = handler.type;
}
var constructor = Ext.layout.container.boxOverflow[handlerType];
if (constructor[this.type]) {
constructor = constructor[this.type];
}
this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
},
onLayout: function() {
this.callParent();
// Clear the innerCt size so it doesn't influence the child items.
if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
this.innerCt.setSize(null, null);
}
var me = this,
targetSize = me.getLayoutTargetSize(),
items = me.getVisibleItems(),
calcs = me.calculateChildBoxes(items, targetSize),
boxes = calcs.boxes,
meta = calcs.meta,
handler, method, results;
if (me.autoSize && calcs.meta.desiredSize) {
targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
}
//invoke the overflow handler, if one is configured
if (meta.shortfall > 0) {
handler = me.overflowHandler;
method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
results = handler[method](calcs, targetSize);
if (results) {
if (results.targetSize) {
targetSize = results.targetSize;
}
if (results.recalculate) {
items = me.getVisibleItems(owner);
calcs = me.calculateChildBoxes(items, targetSize);
boxes = calcs.boxes;
}
}
} else {
me.overflowHandler.clearOverflow();
}
me.layoutTargetLastSize = targetSize;
me.childBoxCache = calcs;
me.updateInnerCtSize(targetSize, calcs);
me.updateChildBoxes(boxes);
me.handleTargetOverflow(targetSize);
},
updateChildBoxes: function(boxes) {
var me = this,
i = 0,
length = boxes.length,
animQueue = [],
dd = Ext.dd.DDM.getDDById(me.innerCt.id), // Any DD active on this layout's element (The BoxReorderer plugin does this.)
oldBox, newBox, changed, comp, boxAnim, animCallback;
for (; i < length; i++) {
newBox = boxes[i];
comp = newBox.component;
// If a Component is being drag/dropped, skip positioning it.
// Accomodate the BoxReorderer plugin: Its current dragEl must not be positioned by the layout
if (dd && (dd.getDragEl() === comp.el.dom)) {
continue;
}
changed = false;
oldBox = me.getChildBox(comp);
// If we are animating, we build up an array of Anim config objects, one for each
// child Component which has any changed box properties. Those with unchanged
// properties are not animated.
if (me.animate) {
// Animate may be a config object containing callback.
animCallback = me.animate.callback || me.animate;
boxAnim = {
layoutAnimation: true, // Component Target handler must use set*Calculated*Size
target: comp,
from: {},
to: {},
listeners: {}
};
// Only set from and to properties when there's a change.
// Perform as few Component setter methods as possible.
// Temporarily set the property values that we are not animating
// so that doComponentLayout does not auto-size them.
if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
changed = true;
// boxAnim.from.width = oldBox.width;
boxAnim.to.width = newBox.width;
}
if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
changed = true;
// boxAnim.from.height = oldBox.height;
boxAnim.to.height = newBox.height;
}
if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
changed = true;
// boxAnim.from.left = oldBox.left;
boxAnim.to.left = newBox.left;
}
if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
changed = true;
// boxAnim.from.top = oldBox.top;
boxAnim.to.top = newBox.top;
}
if (changed) {
animQueue.push(boxAnim);
}
} else {
if (newBox.dirtySize) {
if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
me.setItemSize(comp, newBox.width, newBox.height);
}
}
// Don't set positions to NaN
if (isNaN(newBox.left) || isNaN(newBox.top)) {
continue;
}
comp.setPosition(newBox.left, newBox.top);
}
}
// Kick off any queued animations
length = animQueue.length;
if (length) {
// A function which cleans up when a Component's animation is done.
// The last one to finish calls the callback.
var afterAnimate = function(anim) {
// When we've animated all changed boxes into position, clear our busy flag and call the callback.
length -= 1;
if (!length) {
me.layoutBusy = false;
if (Ext.isFunction(animCallback)) {
animCallback();
}
}
};
var beforeAnimate = function() {
me.layoutBusy = true;
};
// Start each box animation off
for (i = 0, length = animQueue.length; i < length; i++) {
boxAnim = animQueue[i];
// Clean up the Component after. Clean up the *layout* after the last animation finishes
boxAnim.listeners.afteranimate = afterAnimate;
// The layout is busy during animation, and may not be called, so set the flag when the first animation begins
if (!i) {
boxAnim.listeners.beforeanimate = beforeAnimate;
}
if (me.animate.duration) {
boxAnim.duration = me.animate.duration;
}
comp = boxAnim.target;
delete boxAnim.target;
// Stop any currently running animation
comp.stopAnimation();
comp.animate(boxAnim);
}
}
},
updateInnerCtSize: function(tSize, calcs) {
var me = this,
mmax = Math.max,
align = me.align,
padding = me.padding,
width = tSize.width,
height = tSize.height,
meta = calcs.meta,
innerCtWidth,
innerCtHeight;
if (me.direction == 'horizontal') {
innerCtWidth = width;
innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
if (align == 'stretch') {
innerCtHeight = height;
}
else if (align == 'middle') {
innerCtHeight = mmax(height, innerCtHeight);
}
} else {
innerCtHeight = height;
innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
if (align == 'stretch') {
innerCtWidth = width;
}
else if (align == 'center') {
innerCtWidth = mmax(width, innerCtWidth);
}
}
me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
// If a calculated width has been found (and this only happens for auto-width vertical docked Components in old Microsoft browsers)
// then, if the Component has not assumed the size of its content, set it to do so.
if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
me.owner.el.setWidth(meta.calculatedWidth);
}
if (me.innerCt.dom.scrollTop) {
me.innerCt.dom.scrollTop = 0;
}
},
handleTargetOverflow: function(previousTargetSize) {
var target = this.getTarget(),
overflow = target.getStyle('overflow'),
newTargetSize;
if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
newTargetSize = this.getLayoutTargetSize();
if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
this.adjustmentPass = true;
this.onLayout();
return true;
}
}
delete this.adjustmentPass;
},
// private
isValidParent : function(item, target, position) {
// Note: Box layouts do not care about order within the innerCt element because it's an absolutely positioning layout
// We only care whether the item is a direct child of the innerCt element.
var itemEl = item.el ? item.el.dom : Ext.getDom(item);
return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
},
// Overridden method from AbstractContainer.
// Used in the base AbstractLayout.beforeLayout method to render all items into.
getRenderTarget: function() {
if (!this.innerCt) {
// the innerCt prevents wrapping and shuffling while the container is resizing
this.innerCt = this.getTarget().createChild({
cls: this.innerCls,
role: 'presentation'
});
this.padding = Ext.util.Format.parseBox(this.padding);
}
return this.innerCt;
},
// private
renderItem: function(item, target) {
this.callParent(arguments);
var me = this,
itemEl = item.getEl(),
style = itemEl.dom.style,
margins = item.margins || item.margin;
// Parse the item's margin/margins specification
if (margins) {
if (Ext.isString(margins) || Ext.isNumber(margins)) {
margins = Ext.util.Format.parseBox(margins);
} else {
Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
}
} else {
margins = Ext.apply({}, me.defaultMargins);
}
// Add any before/after CSS margins to the configured margins, and zero the CSS margins
margins.top += itemEl.getMargin('t');
margins.right += itemEl.getMargin('r');
margins.bottom += itemEl.getMargin('b');
margins.left += itemEl.getMargin('l');
style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
// Item must reference calculated margins.
item.margins = margins;
},
destroy: function() {
Ext.destroy(this.overflowHandler);
this.callParent(arguments);
}
});
Help would be appreciated.

You just need to set your layout config, like this:
Ext.create('Ext.panel.Panel', {
layout: {type: 'hbox', pack:'end'}
});
The key there is pack:
Controls how the child items of the container are packed together. Acceptable configuration values for this property are:
'start' : Default
child items are packed together at left side of container
'center' :
child items are packed together at mid-width of container
'end' :
child items are packed together at right side of container
Hope that helps

Related

Is there any way to replace text in ChromiumBrowser like Chrome already has?

I'm making a web editor application using CefSharp WinForms library, but I couldn't find a way to replace text from CefSharp API.
There is a find method in WebBrowserExtensions but no replace method.
Question 1:
Does anyone know where replacing text method is in CefSharp?
Or there is no way to replace text in CefSharp? If yes, I need to find a detour for it.
Question 2:
There are yellow blocks marked found words when I try Find method, but those blocks are not a part of selection range of window object in HTML. Are those blocks made by native not web browser?
Answer:
I made "find and replace" function by myself using javascript, so if someone tries to do something like me then you can use below codes:
var lastsearchedNodeIndex = -1;
var lastSearchedTextIndex = -1;
var lastRange = null;
function getTextLengthFromStartTo(targetNodeIndex) {
var childNodes = editor.childNodes;
var textLength = 0;
if (targetNodeIndex >= childNodes.length) {
return editor.textContent.length;
}
for (var i = 0; i < targetNodeIndex; i++) {
if (childNodes[i].textContent != null) {
textLength += childNodes[i].textContent.length;
}
}
return textLength;
}
function getCurrentCaretIndex() {
var currentCaretIndex = 0;
var doc = editor.ownerDocument || editor.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(editor);
preCaretRange.setEnd(range.endContainer, range.endOffset);
currentCaretIndex = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(editor);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
currentCaretIndex = preCaretTextRange.text.length;
}
return currentCaretIndex;
}
function getCurrentNodeIndexAtCaret(caretIndex) {
if (caretIndex == 0) {
return 0;
}
var currentNodeIndex = -1;
for (var i = 0; i < editor.childNodes.length; i++) {
var frontTextLength = getTextLengthFromStartTo(i);
var backTextLength = getTextLengthFromStartTo(i + 1);
if (caretIndex > frontTextLength && caretIndex <= backTextLength) {
currentNodeIndex = i;
break;
}
}
return currentNodeIndex;
}
function getCurrentTextIndexInNodexAtCaret(nodeIndex, caretIndex) {
var textLength = getTextLengthFromStartTo(nodeIndex);
var textIndex = caretIndex - textLength;
return (textIndex < 0) ? 0 : textIndex;
}
function clearSelection() {
if (window.getSelection().rangeCount > 0) {
if (lastRange != null) {
window.getSelection().removeAllRanges();
lastRange.collapse(true);
window.getSelection().addRange(lastRange);
}
}
}
function getTextNodesIn(node) {
var textNodes = [];
if (node.nodeType == 3) {
textNodes.push(node);
} else {
var children = node.childNodes;
for (var i = 0, len = children.length; i < len; ++i) {
textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
}
}
return textNodes;
}
function setSelectionRange(el, start, end) {
if (document.createRange && window.getSelection) {
var range = document.createRange();
range.selectNodeContents(el);
var textNodes = getTextNodesIn(el);
var foundStart = false;
var charCount = 0, endCharCount;
for (var i = 0, textNode; textNode = textNodes[i++]; ) {
endCharCount = charCount + textNode.length;
if (!foundStart && start >= charCount && (start < endCharCount || (start == endCharCount && i <= textNodes.length))) {
range.setStart(textNode, start - charCount);
foundStart = true;
}
if (foundStart && end <= endCharCount) {
range.setEnd(textNode, end - charCount);
break;
}
charCount = endCharCount;
}
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
lastRange = range;
sel.anchorNode.parentElement.scrollIntoView();
} else if (document.selection && document.body.createTextRange) {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(true);
textRange.moveEnd("character", end);
textRange.moveStart("character", start);
textRange.select();
}
}
function findText(text, caseSensitive) {
var currentCaretIndex = getCurrentCaretIndex();
clearSelection();
var regex;
if (caseSensitive) {
regex = text;
} else {
regex = new RegExp(text, "gi");
}
var childNodes = editor.childNodes;
var startNodeIndex = getCurrentNodeIndexAtCaret(currentCaretIndex);
var endNodeIndex = childNodes.length;
var startTextIndex = 0;
if (window.getSelection().focusOffset == 1) {
startTextIndex = lastSearchedTextIndex + 1;
} else {
startTextIndex = getCurrentTextIndexInNodexAtCaret(startNodeIndex, currentCaretIndex);
}
var searchedTextIndex = -1;
var searchedNodeIndex = 0;
var searchTargetSentence = null;
var searchLoopCount = 0;
if (currentCaretIndex == editor.textContent.length) {
startNodeIndex = 0;
startTextIndex = 0;
}
do
{
for (var i = startNodeIndex; i < endNodeIndex; i++) {
if (typeof (childNodes[i].textContent) == undefined || childNodes[i].textContent == null) {
startTextIndex = 0;
continue;
}
if (startTextIndex == childNodes[i].textContent.length) {
startTextIndex = 0;
continue;
}
if (startTextIndex > 0) {
searchTargetSentence = childNodes[i].textContent.substring(startTextIndex, childNodes[i].textContent.length);
} else {
searchTargetSentence = childNodes[i].textContent;
}
searchedTextIndex = searchTargetSentence.search(regex);
if (searchedTextIndex > -1) {
searchedTextIndex += startTextIndex;
searchedNodeIndex = i;
break;
}
startTextIndex = 0;
}
if (searchedTextIndex == -1) {
endNodeIndex = startNodeIndex + 1;
startNodeIndex = 0;
searchLoopCount++;
}
} while (searchLoopCount < 2 && searchedTextIndex == -1);
lastsearchedNodeIndex = searchedNodeIndex;
lastSearchedTextIndex = searchedTextIndex;
if (searchedNodeIndex > -1 && searchedTextIndex > -1) {
var textStartIndex = getTextLengthFromStartTo(searchedNodeIndex) + searchedTextIndex;
setSelectionRange(editor, textStartIndex, textStartIndex + text.length);
return true;
} else {
return false;
}
}
function replaceText(textToFind, textToReplace, caseSensitive) {
if (findText(textToFind, caseSensitive) == true) {
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode(document.createTextNode(textToReplace));
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.text = textToReplace;
}
return true;
} else {
return false;
}
}
There are no replace text method in CefSharp.
I think you have two options
Implement in javascript/html in the browser (DIY or something
like Tiny)
Manipulating the html from C# using GetSourceAsync and LoadHtml (Documentation)
Second question - I think you may be able to at least read the hits using the FindHandler. Have not tested this myself.

Scrolling through an array

So I have a project in GameMaker, which has a chatbox. The messages for this are stored in an array. I would like to be able to scroll through this array, so I can view earlier chat messages.
This is what I currently have:
Create Event
chatLog[0] = "";
chatIndex = 0;
Step Event
if (chatIndex > 0) {
if (mouse_wheel_down()) {
chatIndex--;
}
}
if (chatIndex < array_length_1d(chatLog) - 1) {
if (mouse_wheel_up()) {
chatIndex++;
}
}
var _maxLines = 5;
for (i = 0; i < _maxLines; i++) {
if (i > (array_length_1d(chatLog) - 1)) { exit; }
var _chatLength = array_length_1d(chatLog) - 1;
draw_text(0, 50 - chatHeight, chatLog[_chatLength - i + chatIndex]);
}
First, for convenience of being able to add messages to front / remove them from the back (once there are too many), let's suppose that the log is a list, item 0 being the newest message,
chatLog = ds_list_create();
chatIndex = 0;
for (var i = 1; i <= 15; i++) {
ds_list_insert(chatLog, 0, "message " + string(i));
}
then, the Step Draw event can use information from the list to clamp scroll offset range and draw items:
var maxLines = 5;
// scrolling:
var dz = (mouse_wheel_up() - mouse_wheel_down()) * 3;
if (dz != 0) {
chatIndex = clamp(chatIndex + dz, 0, ds_list_size(chatLog) - maxLines);
}
// drawing:
var i = chatIndex;
var _x = 40;
var _y = 200;
repeat (maxLines) {
var m = chatLog[|i++];
if (m == undefined) break; // reached the end of the list
draw_text(_x, _y, m);
_y -= string_height(m); // draw the next item above the current one
}
live demo

React client tries to access server resource without access to it gets 404

I believe my react code is trying to access a server directory after its compiled and sent to the client. This means when it looks for the gameLogic.js and style.css files it cant locate them. I'm wondering how I would go about getting the react component im working on to get a copy of them and send them off to the remote client. I get the following errors.
pages/game.js
import * as React from "react";
import Layout from "../components/Layout";
import Separator from "../components/Separator";
import CanvasCanvas from "../components/CanvasCanvas";
export default class extends React.Component {
render() {
return (
<Layout>
<main>
<div className="loginBox5">
<Separator height={50}/>
<div className="center">
<h1>Game Play:</h1>
<Separator height={50}/>
<div id="PlayAreaImg" className="gameContainer">
<CanvasCanvas id={"Memes"}/>
</div>
</div>
<Separator height={350}/>
</div>
</main>
</Layout>
)
}
}
src/gameLogic.js
var keyState = {};
window.addEventListener('keydown',function(e){
keyState[e.keyCode || e.which] = true;
},true);
window.addEventListener('keyup',function(e){
keyState[e.keyCode || e.which] = false;
},true);
x = 100;
function drawObj(ctx, object){
var x = object[0];
var y = object[1];
var wid = object[2];
var hei = object[3];
var r = object[4];
var g = object[5];
var b = object[6];
var t = object[7];
// Renderer usage: Canvas context, x position, y position, object height, object width, red, green, blue, transparency
ctx.fillStyle = "rgba("+String(r)+","+String(g)+","+String(b)+","+String(t)+")"; // colour ball
ctx.fillRect (x, y, wid, hei); // render ball
return ctx;
}
function renderAll(objects){
console.log("### - Render: Starting - ###");
for (var i = 0; i < objects.length; i++) {
// Iterate over numeric indexes from 0 to 5, as everyone expects.
}
console.log("### - Render: Complete - ###");
}
//Define generic move function
function transformR(object, moveAmount, canvasHeight, canvasWidth){
if (keyState[37]){
object[0] -= moveAmount
// console.log("left");
}
if (keyState[38]){
object[1] -= moveAmount
if (object[1] < 0){
// console.log("Top Edge")
object[1] = 0;
}
// console.log("up");
}
if (keyState[39]){
object[0] += moveAmount
// console.log("right");
}
if (keyState[40]){
object[1] += moveAmount
if (object[1] > (canvasHeight-object[3])){
// console.log("Bottom Edge")
object[1] = canvasHeight-object[3];
}
// console.log("down");
}
return object;
}
function transformL(object, moveAmount, canvasHeight, canvasWidth){
if (keyState[65]){
object[0] -= moveAmount
// console.log("left");
}
if (keyState[87]){
object[1] -= moveAmount
if (object[1] < 0){
// console.log("Top Edge")
object[1] = 0;
}
// console.log("up");
}
if (keyState[68]){
object[0] += moveAmount
// console.log("right");
}
if (keyState[83]){
object[1] += moveAmount
if (object[1] > (canvasHeight-object[3])){
// console.log("Bottom Edge")
object[1] = canvasHeight-object[3];
}
// console.log("down");
}
return object;
}
function collisonDetect(ball, paddle){
if (ball[0] < paddle[0] + paddle[2] &&
ball[0] + ball[2] > paddle[0] &&
ball[1] < paddle[1] + paddle[3] &&
ball[3] + ball[1] > paddle[1]) {
ball[8] = -ball[8];
ball[9] = -ball[9];
console.log("inside");
} else {
// console.log("not touching/inside");
}
return ball;
}
function ballMotion(height, width, ball, rightPaddle, leftPaddle){
var x = ball[0];
var y = ball[1];
// collision detection
ball = collisonDetect(ball, leftPaddle);
ball = collisonDetect(ball, rightPaddle);
var xSpeed = ball[8];
var ySpeed = ball[9];
x += xSpeed;
y += ySpeed;
// sides collison detection
if (y <= 0){
y = 0;
ySpeed = -ySpeed;
}
if (y >= height-ball[2]) {
y = height-ball[2];
ySpeed = -ySpeed;
}
if (x <= 0) {
x = 0;
xSpeed = -xSpeed;
leftPoints +=1
}
if (x >= width-ball[3]) {
x = width-ball[3];
xSpeed = -xSpeed;
rightPoints +=1
}
// assign new values
ball[0] = x;
ball[1] = y;
ball[8] = xSpeed;
ball[9] = ySpeed;
return ball;
}
function onPositionUpdate(position){
var lat = position.coords.latitude;
var lng = position.coords.longitude;
console.log("Current position: " + lat + " " + lng);
}
function onDown(event){
cx = event.pageX;
cy = event.pageY;
console.log(cx, cy)
}
// Define objects as follows
// Renderer usage: Canvas context, x position, y position, object height, object width, red, green, blue, transparency
// Cut down usage: X, Y, height, width, red, green, blue, transparency
if (window.innerWidth < window.innerHeight) {
ballDim = [window.innerWidth*.02, window.innerWidth*.02]
} else {
ballDim = [window.innerHeight*.02, window.innerHeight*.02]
}
var ball = [window.innerWidth/2-((window.innerWidth*.02)/2), window.innerHeight*.8*.5-((window.innerHeight*.08)/2), ballDim[0], ballDim[1],200 ,200 ,200 ,3 , 3, 2];
var leftPaddle = [window.innerWidth*.01, window.innerHeight*.8*.5-((window.innerHeight*.08)/2), window.innerWidth*.01, window.innerHeight*.08, 0, 0, 200, 3];
var rightPaddle = [window.innerWidth*.8-(window.innerWidth*.01)-(window.innerWidth*.01), window.innerHeight*.8*.5-((window.innerHeight*.08)/2), window.innerWidth*.01, window.innerHeight*.08, 255, 100, 0, 3];
var leftPoints = 0;
var rightPoints = 0;
// Define gameLoop
function gameLoop(x,y) {
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(onPositionUpdate);
} else {
console.log("navigator.geolocation is not available");
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener("mousedown",onDown,false);
var width = window.innerWidth*.8;
var height = window.innerHeight*.8
ctx.canvas.width = width;
ctx.canvas.height = height;
var moveAmount = 3;
var motionTicker = + new Date()
// console.log(motionTicker)
// move checking function
leftPaddle[0] = window.innerWidth*.01;
rightPaddle[0] = window.innerWidth*.8-(window.innerWidth*.01)-(window.innerWidth*.01);
leftPaddle = transformL(leftPaddle, moveAmount, height, width);
rightPaddle = transformR(rightPaddle, moveAmount, height, width);
ball = ballMotion(height, width, ball, rightPaddle, leftPaddle);
ctx.save();
ctx.clearRect(0,0,width,height);
// Render objects in frame
drawObj(ctx, ball);
drawObj(ctx, leftPaddle);
drawObj(ctx, rightPaddle);
ctx.font = String(window.innerWidth*.05)+"px Arial";
ctx.fillStyle = "white";
ctx.fillText(String(rightPoints)+" - "+String(leftPoints), window.innerWidth*.333, window.innerHeight*.1);
ctx.restore();
setTimeout(gameLoop, 1);
await this.forceUpdate();
this.state = {motionTicker}
}
/components/CanvasCanvas.js
import * as React from "react";
export default class extends React.Component {
render() {
return (
<canvas ref={"canvas"} id = {"canvas"} width={640} height={425}/>
)
}
async componentDidMount() {
const script = document.createElement("script");
console.log("ln14")
script.src = "../src/gameLogic.js";
script.async = true;
// console.log(script);
document.head.appendChild(script);
console.log(script);
await this.setState(
{
text: this.props.text,
...this.state
}
);
await this.forceUpdate();
const canvas = this.refs.canvas;
const ctx = canvas.getContext("2d");
ctx.fillText((this.state && this.state.text) ? this.state.text : "Not initialised (nullcheck)", 210, 75);
}
}
Expected result is the gameLogic js file will render its output inside the canvas element and forceUpdate it at the end of each 'frame'.
And the actual result is a string of 404's as follows:
http://localhost:3000/css/style.css net::ERR_ABORTED 404 (Not Found)
index.js:1 Warning: Extra attributes from the server: deluminate_imagetype
GET http://localhost:3000/src/gameLogic.js net::ERR_ABORTED 404 (Not Found)
Thanks for any help you can give in advance.
If you want to access these files after compilation put them inside the static folder for example script.src = "/static/gameLogic.js"
Or use dynamic import
import dynamic from 'next/dynamic'
const gameLogic = dynamic(() => import(`../src/gameLogic.js`))
dynamic-import doc

mxGraph connection handler mouse cursor does not change to hand cursor

I created a new mxgraph react project.
When mouse moved to vertex cursor changes to move_cursor. but I want to create a link and cursor will be hand cursor. how can i solve this problem?
There is a code snippet about connection settings.
settingConnection = () => {
const { graph } = this.state;
mxConstraintHandler.prototype.intersects = function(
icon,
point,
source,
existingEdge
) {
return !source || existingEdge || mxUtils.intersects(icon.bounds, point);
};
var mxConnectionHandlerUpdateEdgeState =
mxConnectionHandler.prototype.updateEdgeState;
mxConnectionHandler.prototype.updateEdgeState = function(pt, constraint) {
if (pt != null && this.previous != null) {
var constraints = this.graph.getAllConnectionConstraints(this.previous);
var nearestConstraint = null;
var dist = null;
for (var i = 0; i < constraints.length; i++) {
var cp = this.graph.getConnectionPoint(this.previous, constraints[i]);
if (cp != null) {
var tmp =
(cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);
if (dist == null || tmp < dist) {
nearestConstraint = constraints[i];
dist = tmp;
}
}
}
if (nearestConstraint != null) {
this.sourceConstraint = nearestConstraint;
}
// In case the edge style must be changed during the preview:
// this.edgeState.style['edgeStyle'] = 'orthogonalEdgeStyle';
// And to use the new edge style in the new edge inserted into the graph,
// update the cell style as follows:
//this.edgeState.cell.style = mxUtils.setStyle(this.edgeState.cell.style, 'edgeStyle', this.edgeState.style['edgeStyle']);
}
mxConnectionHandlerUpdateEdgeState.apply(this, arguments);
};
if (graph.connectionHandler.connectImage == null) {
graph.connectionHandler.isConnectableCell = function(cell) {
return false;
};
mxEdgeHandler.prototype.isConnectableCell = function(cell) {
return graph.connectionHandler.isConnectableCell(cell);
};
}
graph.getAllConnectionConstraints = function(terminal) {
if (terminal != null && this.model.isVertex(terminal.cell)) {
return [
new mxConnectionConstraint(new mxPoint(0.5, 0), true),
new mxConnectionConstraint(new mxPoint(0, 0.5), true),
new mxConnectionConstraint(new mxPoint(1, 0.5), true),
new mxConnectionConstraint(new mxPoint(0.5, 1), true)
];
}
return null;
};
// Connect preview
graph.connectionHandler.createEdgeState = function(me) {
var edge = graph.createEdge(
null,
null,
"Edge",
null,
null,
"edgeStyle=orthogonalEdgeStyle"
);
return new mxCellState(
this.graph.view,
edge,
this.graph.getCellStyle(edge)
);
};
};
Mouse cursor only change to move cursor, but I want to changes to hand cursor when mouse moved to vertex.
When I deleted some codes,
var mxConnectionHandlerUpdateEdgeState =
mxConnectionHandler.prototype.updateEdgeState;
mxConnectionHandler.prototype.updateEdgeState = function(pt, constraint) {
if (pt != null && this.previous != null) {
var constraints = this.graph.getAllConnectionConstraints(this.previous);
var nearestConstraint = null;
var dist = null;
for (var i = 0; i < constraints.length; i++) {
var cp = this.graph.getConnectionPoint(this.previous, constraints[i]);
if (cp != null) {
var tmp =
(cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);
if (dist == null || tmp < dist) {
nearestConstraint = constraints[i];
dist = tmp;
}
}
}
if (nearestConstraint != null) {
this.sourceConstraint = nearestConstraint;
}
// In case the edge style must be changed during the preview:
// this.edgeState.style['edgeStyle'] = 'orthogonalEdgeStyle';
// And to use the new edge style in the new edge inserted into the graph,
// update the cell style as follows:
//this.edgeState.cell.style = mxUtils.setStyle(this.edgeState.cell.style, 'edgeStyle', this.edgeState.style['edgeStyle']);
}
mxConnectionHandlerUpdateEdgeState.apply(this, arguments);
};
if (graph.connectionHandler.connectImage == null) {
graph.connectionHandler.isConnectableCell = function(cell) {
return false;
};
mxEdgeHandler.prototype.isConnectableCell = function(cell) {
return graph.connectionHandler.isConnectableCell(cell);
};
}
And I wrote this codes,
// Enables connect preview for the default edge style
graph.connectionHandler.createEdgeState = function(me) {
var edge = graph.createEdge(null, null, null, null, null);
return new gr.mxCellState(
this.graph.view,
edge,
this.graph.getCellStyle(edge)
);
I solve this problem :)

Looking for a solution to replace tags in a loop where template also contains tables

I have the following docx file:
%LOOP=PolicyRelationship,NAME=Life,KEY=(PolicyNo=Policy.PolicyNo,Relation='INSR')%
%Life.EntityNo% - %Life.Name1% %Life.Name2%
%ENDLOOP%
The following is a table with a header row
Cover Type Sum Insured Modal Premium
BenefitVal SumValue ModalValue
This is the last line of the document.
I am looping through LOOP blocks iteratively - replacing each variable with data
All remaining text is being cut from wordDoc and pasted to remainingParagraphs then re-pasted at the end after the loop values have been pasted back in
Not all paragraphs are being processed this way due to the condition
if (wordDoc.Paragraphs[i].ParentContainer == Container.Body)
condition. Without this condition all paragraphs are processed in the right order but the XML is corrupt. With this condition the table values are not transferred and thus appear incorrectly BEFORE the loop values.
If there is a simpler approach without all the cutting and pastings that would be ideal
This is my current code snippet:
private void ProcessRepeatingText(DocX wordDoc, Dictionary<string, DocumentView> views)
{
var textDoc = wordDoc.Text;
var opn = 0;
while (opn != -1)
{
int cls, cma;
string tag, dto, rsn, key, where;
object repo;
//
// Get each loop DataView that has been defined, select a collection of data and store it in "views"
//
opn = textDoc.IndexOf("%LOOP=", StringComparison.OrdinalIgnoreCase);
if (opn == -1) break;
cls = textDoc.IndexOf("%", opn + 1, StringComparison.OrdinalIgnoreCase);
tag = textDoc.Substring(opn, cls - opn + 1);
cma = tag.IndexOf(",", StringComparison.OrdinalIgnoreCase);
dto = tag.Substring(6, cma - 6);
opn = tag.IndexOf("NAME=", cma, StringComparison.OrdinalIgnoreCase);
cls = tag.IndexOf(",", opn + 5, StringComparison.OrdinalIgnoreCase);
rsn = tag.Substring(opn + 5, cls - opn - 5);
cma = tag.IndexOf(",", cls, StringComparison.OrdinalIgnoreCase);
opn = tag.IndexOf("KEY=(", cma, StringComparison.OrdinalIgnoreCase);
cls = tag.IndexOf(")", opn + 4, StringComparison.OrdinalIgnoreCase);
key = tag.Substring(opn + 5, cls - opn - 5);
where = BuildWhereClause(dto, key, views);
repo = _baseRepository.CreateInstance(dto + "Repository");
var sec = repo.GetType().GetMethod("GetWhere").Invoke(repo, new object[] { where });
views.Add(rsn, new DocumentView { Rsn = rsn, Dto = dto, Data = sec, Pointer = 0 });
var loopTag = tag;
var i = -1;
var startAt = 0;
var tagBlocks = new List<TagBlock>();
opn = textDoc.IndexOf(loopTag, StringComparison.OrdinalIgnoreCase);
while (opn != -1)
{
if (textDoc.Substring(opn, 6) == "%LOOP=")
{
i++;
cls = textDoc.IndexOf("%", opn + 1, StringComparison.OrdinalIgnoreCase);
tagBlocks.Add(new TagBlock { From = opn, Upto = -1, FromIndex = -1, UptoIndex = -1 });
tagBlocks[i].FromIndex = IndexOfParagraph(wordDoc, textDoc.Substring(opn, cls - opn + 1), ref startAt);
opn = opn + 6;
}
if (textDoc.Substring(opn, 8) == "%ENDLOOP")
{
tagBlocks[i].Upto = opn;
if (tagBlocks[i].FromIndex != -1)
{
tagBlocks[i].UptoIndex = IndexOfParagraph(wordDoc, textDoc.Substring(opn, 9), ref startAt);
}
i--;
opn = opn + 8;
}
if (i == -1) break;
opn++;
}
var remainingParagraphs = new List<Novacode.Paragraph>();
for (i = tagBlocks[0].UptoIndex + 1; i < wordDoc.Paragraphs.Count; i++)
{
// if (wordDoc.Paragraphs[i].ParentContainer == ContainerType.Body)
// {
remainingParagraphs.Add(wordDoc.Paragraphs[i]);
wordDoc.RemoveParagraphAt(i);
i--;
// }
}
var loopDoc = DocX.Create(new MemoryStream());
if (tagBlocks[0].FromIndex != -1)
{
if (tagBlocks[0].UptoIndex != -1)
{
for (i = tagBlocks[0].FromIndex + 1; i < tagBlocks[0].UptoIndex; i++)
{
loopDoc.InsertParagraph(wordDoc.Paragraphs[i]);
}
for (i = tagBlocks[0].UptoIndex; i > tagBlocks[0].FromIndex; i--)
{
wordDoc.RemoveParagraphAt(i);
}
}
wordDoc.RemoveParagraphAt(tagBlocks[0].FromIndex);
}
else
{
opn = tagBlocks[0].From;
cls = textDoc.IndexOf("%", opn + 1, StringComparison.OrdinalIgnoreCase);
tag = textDoc.Substring(opn, cls - opn + 1);
var paragraph = wordDoc.Paragraphs.FirstOrDefault(x => x.Text.Contains(tag));
if (paragraph != null)
{
paragraph.ReplaceText(tag, "");
paragraph.ReplaceText("%ENDLOOP%", "");
}
}
var loopTxt = loopDoc.Text;
//
// Now get the secondary DataView data from "views"
//
DocumentView view;
if (views.TryGetValue(rsn, out view) != true)
{
return;
}
view.Pointer = 0;
var list = (IList)view.Data;
for (view.Pointer = 0; view.Pointer < list.Count; view.Pointer++)
{
var item = list[view.Pointer];
//
// Process conditional text, with a dependency on this secondary RSN, within this loop
//
loopTxt = ProcessConditionalText(loopDoc, view.Rsn, views, loopTxt);
//
// Process repeating text (LOOP..ENDLOOP) with a dependency on this secondary RSN
//
ProcessRepeatingText(loopDoc, views);
//
// Perform the data tag replacements, for this RSN, within this loop
//
ReplaceParameters(loopDoc, item, view.Rsn);
foreach (var p in loopDoc.Paragraphs)
{
wordDoc.InsertParagraph(p);
}
}
foreach (var p in remainingParagraphs)
{
wordDoc.InsertParagraph(p);
}
wordDoc.Paragraphs.FirstOrDefault(p => p.Text == loopTag)?.Remove(false);
wordDoc.ReplaceText(loopTag, "");
textDoc = wordDoc.Text;
views.Remove(rsn);
opn = 0;
}
}

Resources