How to use getPreviousEquivalentPoint method in wpt

Best JavaScript code snippet using wpt

aryeh_implementation.js

Source:aryeh_implementation.js Github

copy

Full Screen

...3520 }3521 // "Return null."3522 return null;3523}3524function getPreviousEquivalentPoint(node, offset) {3525 // "If node's length is zero, return null."3526 if (getNodeLength(node) == 0) {3527 return null;3528 }3529 // "If offset is 0, and node's parent is not null, and node is an inline3530 // node, return (node's parent, node's index)."3531 if (offset == 03532 && node.parentNode3533 && isInlineNode(node)) {3534 return [node.parentNode, getNodeIndex(node)];3535 }3536 // "If node has a child with index offset − 1, and that child's length is3537 // not zero, and that child is an inline node, return (that child, that3538 // child's length)."3539 if (0 <= offset - 13540 && offset - 1 < node.childNodes.length3541 && getNodeLength(node.childNodes[offset - 1]) != 03542 && isInlineNode(node.childNodes[offset - 1])) {3543 return [node.childNodes[offset - 1], getNodeLength(node.childNodes[offset - 1])];3544 }3545 // "Return null."3546 return null;3547}3548function getFirstEquivalentPoint(node, offset) {3549 // "While (node, offset)'s previous equivalent point is not null, set3550 // (node, offset) to its previous equivalent point."3551 var prev;3552 while (prev = getPreviousEquivalentPoint(node, offset)) {3553 node = prev[0];3554 offset = prev[1];3555 }3556 // "Return (node, offset)."3557 return [node, offset];3558}3559function getLastEquivalentPoint(node, offset) {3560 // "While (node, offset)'s next equivalent point is not null, set (node,3561 // offset) to its next equivalent point."3562 var next;3563 while (next = getNextEquivalentPoint(node, offset)) {3564 node = next[0];3565 offset = next[1];3566 }3567 // "Return (node, offset)."3568 return [node, offset];3569}3570//@}3571///// Block-extending a range /////3572//@{3573// "A boundary point (node, offset) is a block start point if either node's3574// parent is null and offset is zero; or node has a child with index offset −3575// 1, and that child is either a visible block node or a visible br."3576function isBlockStartPoint(node, offset) {3577 return (!node.parentNode && offset == 0)3578 || (0 <= offset - 13579 && offset - 1 < node.childNodes.length3580 && isVisible(node.childNodes[offset - 1])3581 && (isBlockNode(node.childNodes[offset - 1])3582 || isHtmlElement(node.childNodes[offset - 1], "br")));3583}3584// "A boundary point (node, offset) is a block end point if either node's3585// parent is null and offset is node's length; or node has a child with index3586// offset, and that child is a visible block node."3587function isBlockEndPoint(node, offset) {3588 return (!node.parentNode && offset == getNodeLength(node))3589 || (offset < node.childNodes.length3590 && isVisible(node.childNodes[offset])3591 && isBlockNode(node.childNodes[offset]));3592}3593// "A boundary point is a block boundary point if it is either a block start3594// point or a block end point."3595function isBlockBoundaryPoint(node, offset) {3596 return isBlockStartPoint(node, offset)3597 || isBlockEndPoint(node, offset);3598}3599function blockExtend(range) {3600 // "Let start node, start offset, end node, and end offset be the start3601 // and end nodes and offsets of the range."3602 var startNode = range.startContainer;3603 var startOffset = range.startOffset;3604 var endNode = range.endContainer;3605 var endOffset = range.endOffset;3606 // "If some ancestor container of start node is an li, set start offset to3607 // the index of the last such li in tree order, and set start node to that3608 // li's parent."3609 var liAncestors = getAncestors(startNode).concat(startNode)3610 .filter(function(ancestor) { return isHtmlElement(ancestor, "li") })3611 .slice(-1);3612 if (liAncestors.length) {3613 startOffset = getNodeIndex(liAncestors[0]);3614 startNode = liAncestors[0].parentNode;3615 }3616 // "If (start node, start offset) is not a block start point, repeat the3617 // following steps:"3618 if (!isBlockStartPoint(startNode, startOffset)) do {3619 // "If start offset is zero, set it to start node's index, then set3620 // start node to its parent."3621 if (startOffset == 0) {3622 startOffset = getNodeIndex(startNode);3623 startNode = startNode.parentNode;3624 // "Otherwise, subtract one from start offset."3625 } else {3626 startOffset--;3627 }3628 // "If (start node, start offset) is a block boundary point, break from3629 // this loop."3630 } while (!isBlockBoundaryPoint(startNode, startOffset));3631 // "While start offset is zero and start node's parent is not null, set3632 // start offset to start node's index, then set start node to its parent."3633 while (startOffset == 03634 && startNode.parentNode) {3635 startOffset = getNodeIndex(startNode);3636 startNode = startNode.parentNode;3637 }3638 // "If some ancestor container of end node is an li, set end offset to one3639 // plus the index of the last such li in tree order, and set end node to3640 // that li's parent."3641 var liAncestors = getAncestors(endNode).concat(endNode)3642 .filter(function(ancestor) { return isHtmlElement(ancestor, "li") })3643 .slice(-1);3644 if (liAncestors.length) {3645 endOffset = 1 + getNodeIndex(liAncestors[0]);3646 endNode = liAncestors[0].parentNode;3647 }3648 // "If (end node, end offset) is not a block end point, repeat the3649 // following steps:"3650 if (!isBlockEndPoint(endNode, endOffset)) do {3651 // "If end offset is end node's length, set it to one plus end node's3652 // index, then set end node to its parent."3653 if (endOffset == getNodeLength(endNode)) {3654 endOffset = 1 + getNodeIndex(endNode);3655 endNode = endNode.parentNode;3656 // "Otherwise, add one to end offset.3657 } else {3658 endOffset++;3659 }3660 // "If (end node, end offset) is a block boundary point, break from3661 // this loop."3662 } while (!isBlockBoundaryPoint(endNode, endOffset));3663 // "While end offset is end node's length and end node's parent is not3664 // null, set end offset to one plus end node's index, then set end node to3665 // its parent."3666 while (endOffset == getNodeLength(endNode)3667 && endNode.parentNode) {3668 endOffset = 1 + getNodeIndex(endNode);3669 endNode = endNode.parentNode;3670 }3671 // "Let new range be a new range whose start and end nodes and offsets3672 // are start node, start offset, end node, and end offset."3673 var newRange = startNode.ownerDocument.createRange();3674 newRange.setStart(startNode, startOffset);3675 newRange.setEnd(endNode, endOffset);3676 // "Return new range."3677 return newRange;3678}3679function followsLineBreak(node) {3680 // "Let offset be zero."3681 var offset = 0;3682 // "While (node, offset) is not a block boundary point:"3683 while (!isBlockBoundaryPoint(node, offset)) {3684 // "If node has a visible child with index offset minus one, return3685 // false."3686 if (0 <= offset - 13687 && offset - 1 < node.childNodes.length3688 && isVisible(node.childNodes[offset - 1])) {3689 return false;3690 }3691 // "If offset is zero or node has no children, set offset to node's3692 // index, then set node to its parent."3693 if (offset == 03694 || !node.hasChildNodes()) {3695 offset = getNodeIndex(node);3696 node = node.parentNode;3697 // "Otherwise, set node to its child with index offset minus one, then3698 // set offset to node's length."3699 } else {3700 node = node.childNodes[offset - 1];3701 offset = getNodeLength(node);3702 }3703 }3704 // "Return true."3705 return true;3706}3707function precedesLineBreak(node) {3708 // "Let offset be node's length."3709 var offset = getNodeLength(node);3710 // "While (node, offset) is not a block boundary point:"3711 while (!isBlockBoundaryPoint(node, offset)) {3712 // "If node has a visible child with index offset, return false."3713 if (offset < node.childNodes.length3714 && isVisible(node.childNodes[offset])) {3715 return false;3716 }3717 // "If offset is node's length or node has no children, set offset to3718 // one plus node's index, then set node to its parent."3719 if (offset == getNodeLength(node)3720 || !node.hasChildNodes()) {3721 offset = 1 + getNodeIndex(node);3722 node = node.parentNode;3723 // "Otherwise, set node to its child with index offset and set offset3724 // to zero."3725 } else {3726 node = node.childNodes[offset];3727 offset = 0;3728 }3729 }3730 // "Return true."3731 return true;3732}3733//@}3734///// Recording and restoring overrides /////3735//@{3736function recordCurrentOverrides() {3737 // "Let overrides be a list of (string, string or boolean) ordered pairs,3738 // initially empty."3739 var overrides = [];3740 // "If there is a value override for "createLink", add ("createLink", value3741 // override for "createLink") to overrides."3742 if (getValueOverride("createlink") !== undefined) {3743 overrides.push(["createlink", getValueOverride("createlink")]);3744 }3745 // "For each command in the list "bold", "italic", "strikethrough",3746 // "subscript", "superscript", "underline", in order: if there is a state3747 // override for command, add (command, command's state override) to3748 // overrides."3749 ["bold", "italic", "strikethrough", "subscript", "superscript",3750 "underline"].forEach(function(command) {3751 if (getStateOverride(command) !== undefined) {3752 overrides.push([command, getStateOverride(command)]);3753 }3754 });3755 // "For each command in the list "fontName", "fontSize", "foreColor",3756 // "hiliteColor", in order: if there is a value override for command, add3757 // (command, command's value override) to overrides."3758 ["fontname", "fontsize", "forecolor",3759 "hilitecolor"].forEach(function(command) {3760 if (getValueOverride(command) !== undefined) {3761 overrides.push([command, getValueOverride(command)]);3762 }3763 });3764 // "Return overrides."3765 return overrides;3766}3767function recordCurrentStatesAndValues() {3768 // "Let overrides be a list of (string, string or boolean) ordered pairs,3769 // initially empty."3770 var overrides = [];3771 // "Let node be the first formattable node effectively contained in the3772 // active range, or null if there is none."3773 var node = getAllEffectivelyContainedNodes(getActiveRange())3774 .filter(isFormattableNode)[0];3775 // "If node is null, return overrides."3776 if (!node) {3777 return overrides;3778 }3779 // "Add ("createLink", node's effective command value for "createLink") to3780 // overrides."3781 overrides.push(["createlink", getEffectiveCommandValue(node, "createlink")]);3782 // "For each command in the list "bold", "italic", "strikethrough",3783 // "subscript", "superscript", "underline", in order: if node's effective3784 // command value for command is one of its inline command activated values,3785 // add (command, true) to overrides, and otherwise add (command, false) to3786 // overrides."3787 ["bold", "italic", "strikethrough", "subscript", "superscript",3788 "underline"].forEach(function(command) {3789 if (commands[command].inlineCommandActivatedValues3790 .indexOf(getEffectiveCommandValue(node, command)) != -1) {3791 overrides.push([command, true]);3792 } else {3793 overrides.push([command, false]);3794 }3795 });3796 // "For each command in the list "fontName", "foreColor", "hiliteColor", in3797 // order: add (command, command's value) to overrides."3798 ["fontname", "fontsize", "forecolor", "hilitecolor"].forEach(function(command) {3799 overrides.push([command, commands[command].value()]);3800 });3801 // "Add ("fontSize", node's effective command value for "fontSize") to3802 // overrides."3803 overrides.push(["fontsize", getEffectiveCommandValue(node, "fontsize")]);3804 // "Return overrides."3805 return overrides;3806}3807function restoreStatesAndValues(overrides) {3808 // "Let node be the first formattable node effectively contained in the3809 // active range, or null if there is none."3810 var node = getAllEffectivelyContainedNodes(getActiveRange())3811 .filter(isFormattableNode)[0];3812 // "If node is not null, then for each (command, override) pair in3813 // overrides, in order:"3814 if (node) {3815 for (var i = 0; i < overrides.length; i++) {3816 var command = overrides[i][0];3817 var override = overrides[i][1];3818 // "If override is a boolean, and queryCommandState(command)3819 // returns something different from override, call3820 // execCommand(command)."3821 if (typeof override == "boolean"3822 && myQueryCommandState(command) != override) {3823 myExecCommand(command);3824 // "Otherwise, if override is a string, and command is neither3825 // "createLink" nor "fontSize", and queryCommandValue(command)3826 // returns something not equivalent to override, call3827 // execCommand(command, false, override)."3828 } else if (typeof override == "string"3829 && command != "createlink"3830 && command != "fontsize"3831 && !areEquivalentValues(command, myQueryCommandValue(command), override)) {3832 myExecCommand(command, false, override);3833 // "Otherwise, if override is a string; and command is3834 // "createLink"; and either there is a value override for3835 // "createLink" that is not equal to override, or there is no value3836 // override for "createLink" and node's effective command value for3837 // "createLink" is not equal to override: call3838 // execCommand("createLink", false, override)."3839 } else if (typeof override == "string"3840 && command == "createlink"3841 && (3842 (3843 getValueOverride("createlink") !== undefined3844 && getValueOverride("createlink") !== override3845 ) || (3846 getValueOverride("createlink") === undefined3847 && getEffectiveCommandValue(node, "createlink") !== override3848 )3849 )) {3850 myExecCommand("createlink", false, override);3851 // "Otherwise, if override is a string; and command is "fontSize";3852 // and either there is a value override for "fontSize" that is not3853 // equal to override, or there is no value override for "fontSize"3854 // and node's effective command value for "fontSize" is not loosely3855 // equivalent to override:"3856 } else if (typeof override == "string"3857 && command == "fontsize"3858 && (3859 (3860 getValueOverride("fontsize") !== undefined3861 && getValueOverride("fontsize") !== override3862 ) || (3863 getValueOverride("fontsize") === undefined3864 && !areLooselyEquivalentValues(command, getEffectiveCommandValue(node, "fontsize"), override)3865 )3866 )) {3867 // "Convert override to an integer number of pixels, and set3868 // override to the legacy font size for the result."3869 override = getLegacyFontSize(override);3870 // "Call execCommand("fontSize", false, override)."3871 myExecCommand("fontsize", false, override);3872 // "Otherwise, continue this loop from the beginning."3873 } else {3874 continue;3875 }3876 // "Set node to the first formattable node effectively contained in3877 // the active range, if there is one."3878 node = getAllEffectivelyContainedNodes(getActiveRange())3879 .filter(isFormattableNode)[0]3880 || node;3881 }3882 // "Otherwise, for each (command, override) pair in overrides, in order:"3883 } else {3884 for (var i = 0; i < overrides.length; i++) {3885 var command = overrides[i][0];3886 var override = overrides[i][1];3887 // "If override is a boolean, set the state override for command to3888 // override."3889 if (typeof override == "boolean") {3890 setStateOverride(command, override);3891 }3892 // "If override is a string, set the value override for command to3893 // override."3894 if (typeof override == "string") {3895 setValueOverride(command, override);3896 }3897 }3898 }3899}3900//@}3901///// Deleting the selection /////3902//@{3903// The flags argument is a dictionary that can have blockMerging,3904// stripWrappers, and/or direction as keys.3905function deleteSelection(flags) {3906 if (flags === undefined) {3907 flags = {};3908 }3909 var blockMerging = "blockMerging" in flags ? Boolean(flags.blockMerging) : true;3910 var stripWrappers = "stripWrappers" in flags ? Boolean(flags.stripWrappers) : true;3911 var direction = "direction" in flags ? flags.direction : "forward";3912 // "If the active range is null, abort these steps and do nothing."3913 if (!getActiveRange()) {3914 return;3915 }3916 // "Canonicalize whitespace at the active range's start."3917 canonicalizeWhitespace(getActiveRange().startContainer, getActiveRange().startOffset);3918 // "Canonicalize whitespace at the active range's end."3919 canonicalizeWhitespace(getActiveRange().endContainer, getActiveRange().endOffset);3920 // "Let (start node, start offset) be the last equivalent point for the3921 // active range's start."3922 var start = getLastEquivalentPoint(getActiveRange().startContainer, getActiveRange().startOffset);3923 var startNode = start[0];3924 var startOffset = start[1];3925 // "Let (end node, end offset) be the first equivalent point for the active3926 // range's end."3927 var end = getFirstEquivalentPoint(getActiveRange().endContainer, getActiveRange().endOffset);3928 var endNode = end[0];3929 var endOffset = end[1];3930 // "If (end node, end offset) is not after (start node, start offset):"3931 if (getPosition(endNode, endOffset, startNode, startOffset) !== "after") {3932 // "If direction is "forward", call collapseToStart() on the context3933 // object's Selection."3934 //3935 // Here and in a few other places, we check rangeCount to work around a3936 // WebKit bug: it will sometimes incorrectly remove ranges from the3937 // selection if nodes are removed, so collapseToStart() will throw.3938 // This will break everything if we're using an actual selection, but3939 // if getActiveRange() is really just returning globalRange and that's3940 // all we care about, it will work fine. I only add the extra check3941 // for errors I actually hit in testing.3942 if (direction == "forward") {3943 if (getSelection().rangeCount) {3944 getSelection().collapseToStart();3945 }3946 getActiveRange().collapse(true);3947 // "Otherwise, call collapseToEnd() on the context object's Selection."3948 } else {3949 getSelection().collapseToEnd();3950 getActiveRange().collapse(false);3951 }3952 // "Abort these steps."3953 return;3954 }3955 // "If start node is a Text node and start offset is 0, set start offset to3956 // the index of start node, then set start node to its parent."3957 if (startNode.nodeType == Node.TEXT_NODE3958 && startOffset == 0) {3959 startOffset = getNodeIndex(startNode);3960 startNode = startNode.parentNode;3961 }3962 // "If end node is a Text node and end offset is its length, set end offset3963 // to one plus the index of end node, then set end node to its parent."3964 if (endNode.nodeType == Node.TEXT_NODE3965 && endOffset == getNodeLength(endNode)) {3966 endOffset = 1 + getNodeIndex(endNode);3967 endNode = endNode.parentNode;3968 }3969 // "Call collapse(start node, start offset) on the context object's3970 // Selection."3971 getSelection().collapse(startNode, startOffset);3972 getActiveRange().setStart(startNode, startOffset);3973 // "Call extend(end node, end offset) on the context object's Selection."3974 getSelection().extend(endNode, endOffset);3975 getActiveRange().setEnd(endNode, endOffset);3976 // "Let start block be the active range's start node."3977 var startBlock = getActiveRange().startContainer;3978 // "While start block's parent is in the same editing host and start block3979 // is an inline node, set start block to its parent."3980 while (inSameEditingHost(startBlock, startBlock.parentNode)3981 && isInlineNode(startBlock)) {3982 startBlock = startBlock.parentNode;3983 }3984 // "If start block is neither a block node nor an editing host, or "span"3985 // is not an allowed child of start block, or start block is a td or th,3986 // set start block to null."3987 if ((!isBlockNode(startBlock) && !isEditingHost(startBlock))3988 || !isAllowedChild("span", startBlock)3989 || isHtmlElement(startBlock, ["td", "th"])) {3990 startBlock = null;3991 }3992 // "Let end block be the active range's end node."3993 var endBlock = getActiveRange().endContainer;3994 // "While end block's parent is in the same editing host and end block is3995 // an inline node, set end block to its parent."3996 while (inSameEditingHost(endBlock, endBlock.parentNode)3997 && isInlineNode(endBlock)) {3998 endBlock = endBlock.parentNode;3999 }4000 // "If end block is neither a block node nor an editing host, or "span" is4001 // not an allowed child of end block, or end block is a td or th, set end4002 // block to null."4003 if ((!isBlockNode(endBlock) && !isEditingHost(endBlock))4004 || !isAllowedChild("span", endBlock)4005 || isHtmlElement(endBlock, ["td", "th"])) {4006 endBlock = null;4007 }4008 // "Record current states and values, and let overrides be the result."4009 var overrides = recordCurrentStatesAndValues();4010 // "If start node and end node are the same, and start node is an editable4011 // Text node:"4012 if (startNode == endNode4013 && isEditable(startNode)4014 && startNode.nodeType == Node.TEXT_NODE) {4015 // "Call deleteData(start offset, end offset − start offset) on start4016 // node."4017 startNode.deleteData(startOffset, endOffset - startOffset);4018 // "Canonicalize whitespace at (start node, start offset), with fix4019 // collapsed space false."4020 canonicalizeWhitespace(startNode, startOffset, false);4021 // "If direction is "forward", call collapseToStart() on the context4022 // object's Selection."4023 if (direction == "forward") {4024 if (getSelection().rangeCount) {4025 getSelection().collapseToStart();4026 }4027 getActiveRange().collapse(true);4028 // "Otherwise, call collapseToEnd() on the context object's Selection."4029 } else {4030 getSelection().collapseToEnd();4031 getActiveRange().collapse(false);4032 }4033 // "Restore states and values from overrides."4034 restoreStatesAndValues(overrides);4035 // "Abort these steps."4036 return;4037 }4038 // "If start node is an editable Text node, call deleteData() on it, with4039 // start offset as the first argument and (length of start node − start4040 // offset) as the second argument."4041 if (isEditable(startNode)4042 && startNode.nodeType == Node.TEXT_NODE) {4043 startNode.deleteData(startOffset, getNodeLength(startNode) - startOffset);4044 }4045 // "Let node list be a list of nodes, initially empty."4046 //4047 // "For each node contained in the active range, append node to node list4048 // if the last member of node list (if any) is not an ancestor of node;4049 // node is editable; and node is not a thead, tbody, tfoot, tr, th, or td."4050 var nodeList = getContainedNodes(getActiveRange(),4051 function(node) {4052 return isEditable(node)4053 && !isHtmlElement(node, ["thead", "tbody", "tfoot", "tr", "th", "td"]);4054 }4055 );4056 // "For each node in node list:"4057 for (var i = 0; i < nodeList.length; i++) {4058 var node = nodeList[i];4059 // "Let parent be the parent of node."4060 var parent_ = node.parentNode;4061 // "Remove node from parent."4062 parent_.removeChild(node);4063 // "If the block node of parent has no visible children, and parent is4064 // editable or an editing host, call createElement("br") on the context4065 // object and append the result as the last child of parent."4066 if (![].some.call(getBlockNodeOf(parent_).childNodes, isVisible)4067 && (isEditable(parent_) || isEditingHost(parent_))) {4068 parent_.appendChild(document.createElement("br"));4069 }4070 // "If strip wrappers is true or parent is not an ancestor container of4071 // start node, while parent is an editable inline node with length 0,4072 // let grandparent be the parent of parent, then remove parent from4073 // grandparent, then set parent to grandparent."4074 if (stripWrappers4075 || (!isAncestor(parent_, startNode) && parent_ != startNode)) {4076 while (isEditable(parent_)4077 && isInlineNode(parent_)4078 && getNodeLength(parent_) == 0) {4079 var grandparent = parent_.parentNode;4080 grandparent.removeChild(parent_);4081 parent_ = grandparent;4082 }4083 }4084 }4085 // "If end node is an editable Text node, call deleteData(0, end offset) on4086 // it."4087 if (isEditable(endNode)4088 && endNode.nodeType == Node.TEXT_NODE) {4089 endNode.deleteData(0, endOffset);4090 }4091 // "Canonicalize whitespace at the active range's start, with fix collapsed4092 // space false."4093 canonicalizeWhitespace(getActiveRange().startContainer, getActiveRange().startOffset, false);4094 // "Canonicalize whitespace at the active range's end, with fix collapsed4095 // space false."4096 canonicalizeWhitespace(getActiveRange().endContainer, getActiveRange().endOffset, false);4097 // "If block merging is false, or start block or end block is null, or4098 // start block is not in the same editing host as end block, or start block4099 // and end block are the same:"4100 if (!blockMerging4101 || !startBlock4102 || !endBlock4103 || !inSameEditingHost(startBlock, endBlock)4104 || startBlock == endBlock) {4105 // "If direction is "forward", call collapseToStart() on the context4106 // object's Selection."4107 if (direction == "forward") {4108 if (getSelection().rangeCount) {4109 getSelection().collapseToStart();4110 }4111 getActiveRange().collapse(true);4112 // "Otherwise, call collapseToEnd() on the context object's Selection."4113 } else {4114 if (getSelection().rangeCount) {4115 getSelection().collapseToEnd();4116 }4117 getActiveRange().collapse(false);4118 }4119 // "Restore states and values from overrides."4120 restoreStatesAndValues(overrides);4121 // "Abort these steps."4122 return;4123 }4124 // "If start block has one child, which is a collapsed block prop, remove4125 // its child from it."4126 if (startBlock.children.length == 14127 && isCollapsedBlockProp(startBlock.firstChild)) {4128 startBlock.removeChild(startBlock.firstChild);4129 }4130 // "If start block is an ancestor of end block:"4131 if (isAncestor(startBlock, endBlock)) {4132 // "Let reference node be end block."4133 var referenceNode = endBlock;4134 // "While reference node is not a child of start block, set reference4135 // node to its parent."4136 while (referenceNode.parentNode != startBlock) {4137 referenceNode = referenceNode.parentNode;4138 }4139 // "Call collapse() on the context object's Selection, with first4140 // argument start block and second argument the index of reference4141 // node."4142 getSelection().collapse(startBlock, getNodeIndex(referenceNode));4143 getActiveRange().setStart(startBlock, getNodeIndex(referenceNode));4144 getActiveRange().collapse(true);4145 // "If end block has no children:"4146 if (!endBlock.hasChildNodes()) {4147 // "While end block is editable and is the only child of its parent4148 // and is not a child of start block, let parent equal end block,4149 // then remove end block from parent, then set end block to4150 // parent."4151 while (isEditable(endBlock)4152 && endBlock.parentNode.childNodes.length == 14153 && endBlock.parentNode != startBlock) {4154 var parent_ = endBlock;4155 parent_.removeChild(endBlock);4156 endBlock = parent_;4157 }4158 // "If end block is editable and is not an inline node, and its4159 // previousSibling and nextSibling are both inline nodes, call4160 // createElement("br") on the context object and insert it into end4161 // block's parent immediately after end block."4162 if (isEditable(endBlock)4163 && !isInlineNode(endBlock)4164 && isInlineNode(endBlock.previousSibling)4165 && isInlineNode(endBlock.nextSibling)) {4166 endBlock.parentNode.insertBefore(document.createElement("br"), endBlock.nextSibling);4167 }4168 // "If end block is editable, remove it from its parent."4169 if (isEditable(endBlock)) {4170 endBlock.parentNode.removeChild(endBlock);4171 }4172 // "Restore states and values from overrides."4173 restoreStatesAndValues(overrides);4174 // "Abort these steps."4175 return;4176 }4177 // "If end block's firstChild is not an inline node, restore states and4178 // values from overrides, then abort these steps."4179 if (!isInlineNode(endBlock.firstChild)) {4180 restoreStatesAndValues(overrides);4181 return;4182 }4183 // "Let children be a list of nodes, initially empty."4184 var children = [];4185 // "Append the first child of end block to children."4186 children.push(endBlock.firstChild);4187 // "While children's last member is not a br, and children's last4188 // member's nextSibling is an inline node, append children's last4189 // member's nextSibling to children."4190 while (!isHtmlElement(children[children.length - 1], "br")4191 && isInlineNode(children[children.length - 1].nextSibling)) {4192 children.push(children[children.length - 1].nextSibling);4193 }4194 // "Record the values of children, and let values be the result."4195 var values = recordValues(children);4196 // "While children's first member's parent is not start block, split4197 // the parent of children."4198 while (children[0].parentNode != startBlock) {4199 splitParent(children);4200 }4201 // "If children's first member's previousSibling is an editable br,4202 // remove that br from its parent."4203 if (isEditable(children[0].previousSibling)4204 && isHtmlElement(children[0].previousSibling, "br")) {4205 children[0].parentNode.removeChild(children[0].previousSibling);4206 }4207 // "Otherwise, if start block is a descendant of end block:"4208 } else if (isDescendant(startBlock, endBlock)) {4209 // "Call collapse() on the context object's Selection, with first4210 // argument start block and second argument start block's length."4211 getSelection().collapse(startBlock, getNodeLength(startBlock));4212 getActiveRange().setStart(startBlock, getNodeLength(startBlock));4213 getActiveRange().collapse(true);4214 // "Let reference node be start block."4215 var referenceNode = startBlock;4216 // "While reference node is not a child of end block, set reference4217 // node to its parent."4218 while (referenceNode.parentNode != endBlock) {4219 referenceNode = referenceNode.parentNode;4220 }4221 // "If reference node's nextSibling is an inline node and start block's4222 // lastChild is a br, remove start block's lastChild from it."4223 if (isInlineNode(referenceNode.nextSibling)4224 && isHtmlElement(startBlock.lastChild, "br")) {4225 startBlock.removeChild(startBlock.lastChild);4226 }4227 // "Let nodes to move be a list of nodes, initially empty."4228 var nodesToMove = [];4229 // "If reference node's nextSibling is neither null nor a block node,4230 // append it to nodes to move."4231 if (referenceNode.nextSibling4232 && !isBlockNode(referenceNode.nextSibling)) {4233 nodesToMove.push(referenceNode.nextSibling);4234 }4235 // "While nodes to move is nonempty and its last member isn't a br and4236 // its last member's nextSibling is neither null nor a block node,4237 // append its last member's nextSibling to nodes to move."4238 if (nodesToMove.length4239 && !isHtmlElement(nodesToMove[nodesToMove.length - 1], "br")4240 && nodesToMove[nodesToMove.length - 1].nextSibling4241 && !isBlockNode(nodesToMove[nodesToMove.length - 1].nextSibling)) {4242 nodesToMove.push(nodesToMove[nodesToMove.length - 1].nextSibling);4243 }4244 // "Record the values of nodes to move, and let values be the result."4245 var values = recordValues(nodesToMove);4246 // "For each node in nodes to move, append node as the last child of4247 // start block, preserving ranges."4248 nodesToMove.forEach(function(node) {4249 movePreservingRanges(node, startBlock, -1);4250 });4251 // "Otherwise:"4252 } else {4253 // "Call collapse() on the context object's Selection, with first4254 // argument start block and second argument start block's length."4255 getSelection().collapse(startBlock, getNodeLength(startBlock));4256 getActiveRange().setStart(startBlock, getNodeLength(startBlock));4257 getActiveRange().collapse(true);4258 // "If end block's firstChild is an inline node and start block's4259 // lastChild is a br, remove start block's lastChild from it."4260 if (isInlineNode(endBlock.firstChild)4261 && isHtmlElement(startBlock.lastChild, "br")) {4262 startBlock.removeChild(startBlock.lastChild);4263 }4264 // "Record the values of end block's children, and let values be the4265 // result."4266 var values = recordValues([].slice.call(endBlock.childNodes));4267 // "While end block has children, append the first child of end block4268 // to start block, preserving ranges."4269 while (endBlock.hasChildNodes()) {4270 movePreservingRanges(endBlock.firstChild, startBlock, -1);4271 }4272 // "While end block has no children, let parent be the parent of end4273 // block, then remove end block from parent, then set end block to4274 // parent."4275 while (!endBlock.hasChildNodes()) {4276 var parent_ = endBlock.parentNode;4277 parent_.removeChild(endBlock);4278 endBlock = parent_;4279 }4280 }4281 // "Let ancestor be start block."4282 var ancestor = startBlock;4283 // "While ancestor has an inclusive ancestor ol in the same editing host4284 // whose nextSibling is also an ol in the same editing host, or an4285 // inclusive ancestor ul in the same editing host whose nextSibling is also4286 // a ul in the same editing host:"4287 while (getInclusiveAncestors(ancestor).some(function(node) {4288 return inSameEditingHost(ancestor, node)4289 && (4290 (isHtmlElement(node, "ol") && isHtmlElement(node.nextSibling, "ol"))4291 || (isHtmlElement(node, "ul") && isHtmlElement(node.nextSibling, "ul"))4292 ) && inSameEditingHost(ancestor, node.nextSibling);4293 })) {4294 // "While ancestor and its nextSibling are not both ols in the same4295 // editing host, and are also not both uls in the same editing host,4296 // set ancestor to its parent."4297 while (!(4298 isHtmlElement(ancestor, "ol")4299 && isHtmlElement(ancestor.nextSibling, "ol")4300 && inSameEditingHost(ancestor, ancestor.nextSibling)4301 ) && !(4302 isHtmlElement(ancestor, "ul")4303 && isHtmlElement(ancestor.nextSibling, "ul")4304 && inSameEditingHost(ancestor, ancestor.nextSibling)4305 )) {4306 ancestor = ancestor.parentNode;4307 }4308 // "While ancestor's nextSibling has children, append ancestor's4309 // nextSibling's firstChild as the last child of ancestor, preserving4310 // ranges."4311 while (ancestor.nextSibling.hasChildNodes()) {4312 movePreservingRanges(ancestor.nextSibling.firstChild, ancestor, -1);4313 }4314 // "Remove ancestor's nextSibling from its parent."4315 ancestor.parentNode.removeChild(ancestor.nextSibling);4316 }4317 // "Restore the values from values."4318 restoreValues(values);4319 // "If start block has no children, call createElement("br") on the context4320 // object and append the result as the last child of start block."4321 if (!startBlock.hasChildNodes()) {4322 startBlock.appendChild(document.createElement("br"));4323 }4324 // "Remove extraneous line breaks at the end of start block."4325 removeExtraneousLineBreaksAtTheEndOf(startBlock);4326 // "Restore states and values from overrides."4327 restoreStatesAndValues(overrides);4328}4329//@}4330///// Splitting a node list's parent /////4331//@{4332function splitParent(nodeList) {4333 // "Let original parent be the parent of the first member of node list."4334 var originalParent = nodeList[0].parentNode;4335 // "If original parent is not editable or its parent is null, do nothing4336 // and abort these steps."4337 if (!isEditable(originalParent)4338 || !originalParent.parentNode) {4339 return;4340 }4341 // "If the first child of original parent is in node list, remove4342 // extraneous line breaks before original parent."4343 if (nodeList.indexOf(originalParent.firstChild) != -1) {4344 removeExtraneousLineBreaksBefore(originalParent);4345 }4346 // "If the first child of original parent is in node list, and original4347 // parent follows a line break, set follows line break to true. Otherwise,4348 // set follows line break to false."4349 var followsLineBreak_ = nodeList.indexOf(originalParent.firstChild) != -14350 && followsLineBreak(originalParent);4351 // "If the last child of original parent is in node list, and original4352 // parent precedes a line break, set precedes line break to true.4353 // Otherwise, set precedes line break to false."4354 var precedesLineBreak_ = nodeList.indexOf(originalParent.lastChild) != -14355 && precedesLineBreak(originalParent);4356 // "If the first child of original parent is not in node list, but its last4357 // child is:"4358 if (nodeList.indexOf(originalParent.firstChild) == -14359 && nodeList.indexOf(originalParent.lastChild) != -1) {4360 // "For each node in node list, in reverse order, insert node into the4361 // parent of original parent immediately after original parent,4362 // preserving ranges."4363 for (var i = nodeList.length - 1; i >= 0; i--) {4364 movePreservingRanges(nodeList[i], originalParent.parentNode, 1 + getNodeIndex(originalParent));4365 }4366 // "If precedes line break is true, and the last member of node list4367 // does not precede a line break, call createElement("br") on the4368 // context object and insert the result immediately after the last4369 // member of node list."4370 if (precedesLineBreak_4371 && !precedesLineBreak(nodeList[nodeList.length - 1])) {4372 nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);4373 }4374 // "Remove extraneous line breaks at the end of original parent."4375 removeExtraneousLineBreaksAtTheEndOf(originalParent);4376 // "Abort these steps."4377 return;4378 }4379 // "If the first child of original parent is not in node list:"4380 if (nodeList.indexOf(originalParent.firstChild) == -1) {4381 // "Let cloned parent be the result of calling cloneNode(false) on4382 // original parent."4383 var clonedParent = originalParent.cloneNode(false);4384 // "If original parent has an id attribute, unset it."4385 originalParent.removeAttribute("id");4386 // "Insert cloned parent into the parent of original parent immediately4387 // before original parent."4388 originalParent.parentNode.insertBefore(clonedParent, originalParent);4389 // "While the previousSibling of the first member of node list is not4390 // null, append the first child of original parent as the last child of4391 // cloned parent, preserving ranges."4392 while (nodeList[0].previousSibling) {4393 movePreservingRanges(originalParent.firstChild, clonedParent, clonedParent.childNodes.length);4394 }4395 }4396 // "For each node in node list, insert node into the parent of original4397 // parent immediately before original parent, preserving ranges."4398 for (var i = 0; i < nodeList.length; i++) {4399 movePreservingRanges(nodeList[i], originalParent.parentNode, getNodeIndex(originalParent));4400 }4401 // "If follows line break is true, and the first member of node list does4402 // not follow a line break, call createElement("br") on the context object4403 // and insert the result immediately before the first member of node list."4404 if (followsLineBreak_4405 && !followsLineBreak(nodeList[0])) {4406 nodeList[0].parentNode.insertBefore(document.createElement("br"), nodeList[0]);4407 }4408 // "If the last member of node list is an inline node other than a br, and4409 // the first child of original parent is a br, and original parent is not4410 // an inline node, remove the first child of original parent from original4411 // parent."4412 if (isInlineNode(nodeList[nodeList.length - 1])4413 && !isHtmlElement(nodeList[nodeList.length - 1], "br")4414 && isHtmlElement(originalParent.firstChild, "br")4415 && !isInlineNode(originalParent)) {4416 originalParent.removeChild(originalParent.firstChild);4417 }4418 // "If original parent has no children:"4419 if (!originalParent.hasChildNodes()) {4420 // "Remove original parent from its parent."4421 originalParent.parentNode.removeChild(originalParent);4422 // "If precedes line break is true, and the last member of node list4423 // does not precede a line break, call createElement("br") on the4424 // context object and insert the result immediately after the last4425 // member of node list."4426 if (precedesLineBreak_4427 && !precedesLineBreak(nodeList[nodeList.length - 1])) {4428 nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);4429 }4430 // "Otherwise, remove extraneous line breaks before original parent."4431 } else {4432 removeExtraneousLineBreaksBefore(originalParent);4433 }4434 // "If node list's last member's nextSibling is null, but its parent is not4435 // null, remove extraneous line breaks at the end of node list's last4436 // member's parent."4437 if (!nodeList[nodeList.length - 1].nextSibling4438 && nodeList[nodeList.length - 1].parentNode) {4439 removeExtraneousLineBreaksAtTheEndOf(nodeList[nodeList.length - 1].parentNode);4440 }4441}4442// "To remove a node node while preserving its descendants, split the parent of4443// node's children if it has any. If it has no children, instead remove it from4444// its parent."4445function removePreservingDescendants(node) {4446 if (node.hasChildNodes()) {4447 splitParent([].slice.call(node.childNodes));4448 } else {4449 node.parentNode.removeChild(node);4450 }4451}4452//@}4453///// Canonical space sequences /////4454//@{4455function canonicalSpaceSequence(n, nonBreakingStart, nonBreakingEnd) {4456 // "If n is zero, return the empty string."4457 if (n == 0) {4458 return "";4459 }4460 // "If n is one and both non-breaking start and non-breaking end are false,4461 // return a single space (U+0020)."4462 if (n == 1 && !nonBreakingStart && !nonBreakingEnd) {4463 return " ";4464 }4465 // "If n is one, return a single non-breaking space (U+00A0)."4466 if (n == 1) {4467 return "\xa0";4468 }4469 // "Let buffer be the empty string."4470 var buffer = "";4471 // "If non-breaking start is true, let repeated pair be U+00A0 U+0020.4472 // Otherwise, let it be U+0020 U+00A0."4473 var repeatedPair;4474 if (nonBreakingStart) {4475 repeatedPair = "\xa0 ";4476 } else {4477 repeatedPair = " \xa0";4478 }4479 // "While n is greater than three, append repeated pair to buffer and4480 // subtract two from n."4481 while (n > 3) {4482 buffer += repeatedPair;4483 n -= 2;4484 }4485 // "If n is three, append a three-element string to buffer depending on4486 // non-breaking start and non-breaking end:"4487 if (n == 3) {4488 buffer +=4489 !nonBreakingStart && !nonBreakingEnd ? " \xa0 "4490 : nonBreakingStart && !nonBreakingEnd ? "\xa0\xa0 "4491 : !nonBreakingStart && nonBreakingEnd ? " \xa0\xa0"4492 : nonBreakingStart && nonBreakingEnd ? "\xa0 \xa0"4493 : "impossible";4494 // "Otherwise, append a two-element string to buffer depending on4495 // non-breaking start and non-breaking end:"4496 } else {4497 buffer +=4498 !nonBreakingStart && !nonBreakingEnd ? "\xa0 "4499 : nonBreakingStart && !nonBreakingEnd ? "\xa0 "4500 : !nonBreakingStart && nonBreakingEnd ? " \xa0"4501 : nonBreakingStart && nonBreakingEnd ? "\xa0\xa0"4502 : "impossible";4503 }4504 // "Return buffer."4505 return buffer;4506}4507function canonicalizeWhitespace(node, offset, fixCollapsedSpace) {4508 if (fixCollapsedSpace === undefined) {4509 // "an optional boolean argument fix collapsed space that defaults to4510 // true"4511 fixCollapsedSpace = true;4512 }4513 // "If node is neither editable nor an editing host, abort these steps."4514 if (!isEditable(node) && !isEditingHost(node)) {4515 return;4516 }4517 // "Let start node equal node and let start offset equal offset."4518 var startNode = node;4519 var startOffset = offset;4520 // "Repeat the following steps:"4521 while (true) {4522 // "If start node has a child in the same editing host with index start4523 // offset minus one, set start node to that child, then set start4524 // offset to start node's length."4525 if (0 <= startOffset - 14526 && inSameEditingHost(startNode, startNode.childNodes[startOffset - 1])) {4527 startNode = startNode.childNodes[startOffset - 1];4528 startOffset = getNodeLength(startNode);4529 // "Otherwise, if start offset is zero and start node does not follow a4530 // line break and start node's parent is in the same editing host, set4531 // start offset to start node's index, then set start node to its4532 // parent."4533 } else if (startOffset == 04534 && !followsLineBreak(startNode)4535 && inSameEditingHost(startNode, startNode.parentNode)) {4536 startOffset = getNodeIndex(startNode);4537 startNode = startNode.parentNode;4538 // "Otherwise, if start node is a Text node and its parent's resolved4539 // value for "white-space" is neither "pre" nor "pre-wrap" and start4540 // offset is not zero and the (start offset − 1)st element of start4541 // node's data is a space (0x0020) or non-breaking space (0x00A0),4542 // subtract one from start offset."4543 } else if (startNode.nodeType == Node.TEXT_NODE4544 && ["pre", "pre-wrap"].indexOf(getComputedStyle(startNode.parentNode).whiteSpace) == -14545 && startOffset != 04546 && /[ \xa0]/.test(startNode.data[startOffset - 1])) {4547 startOffset--;4548 // "Otherwise, break from this loop."4549 } else {4550 break;4551 }4552 }4553 // "Let end node equal start node and end offset equal start offset."4554 var endNode = startNode;4555 var endOffset = startOffset;4556 // "Let length equal zero."4557 var length = 0;4558 // "Let collapse spaces be true if start offset is zero and start node4559 // follows a line break, otherwise false."4560 var collapseSpaces = startOffset == 0 && followsLineBreak(startNode);4561 // "Repeat the following steps:"4562 while (true) {4563 // "If end node has a child in the same editing host with index end4564 // offset, set end node to that child, then set end offset to zero."4565 if (endOffset < endNode.childNodes.length4566 && inSameEditingHost(endNode, endNode.childNodes[endOffset])) {4567 endNode = endNode.childNodes[endOffset];4568 endOffset = 0;4569 // "Otherwise, if end offset is end node's length and end node does not4570 // precede a line break and end node's parent is in the same editing4571 // host, set end offset to one plus end node's index, then set end node4572 // to its parent."4573 } else if (endOffset == getNodeLength(endNode)4574 && !precedesLineBreak(endNode)4575 && inSameEditingHost(endNode, endNode.parentNode)) {4576 endOffset = 1 + getNodeIndex(endNode);4577 endNode = endNode.parentNode;4578 // "Otherwise, if end node is a Text node and its parent's resolved4579 // value for "white-space" is neither "pre" nor "pre-wrap" and end4580 // offset is not end node's length and the end offsetth element of4581 // end node's data is a space (0x0020) or non-breaking space (0x00A0):"4582 } else if (endNode.nodeType == Node.TEXT_NODE4583 && ["pre", "pre-wrap"].indexOf(getComputedStyle(endNode.parentNode).whiteSpace) == -14584 && endOffset != getNodeLength(endNode)4585 && /[ \xa0]/.test(endNode.data[endOffset])) {4586 // "If fix collapsed space is true, and collapse spaces is true,4587 // and the end offsetth code unit of end node's data is a space4588 // (0x0020): call deleteData(end offset, 1) on end node, then4589 // continue this loop from the beginning."4590 if (fixCollapsedSpace4591 && collapseSpaces4592 && " " == endNode.data[endOffset]) {4593 endNode.deleteData(endOffset, 1);4594 continue;4595 }4596 // "Set collapse spaces to true if the end offsetth element of end4597 // node's data is a space (0x0020), false otherwise."4598 collapseSpaces = " " == endNode.data[endOffset];4599 // "Add one to end offset."4600 endOffset++;4601 // "Add one to length."4602 length++;4603 // "Otherwise, break from this loop."4604 } else {4605 break;4606 }4607 }4608 // "If fix collapsed space is true, then while (start node, start offset)4609 // is before (end node, end offset):"4610 if (fixCollapsedSpace) {4611 while (getPosition(startNode, startOffset, endNode, endOffset) == "before") {4612 // "If end node has a child in the same editing host with index end4613 // offset − 1, set end node to that child, then set end offset to end4614 // node's length."4615 if (0 <= endOffset - 14616 && endOffset - 1 < endNode.childNodes.length4617 && inSameEditingHost(endNode, endNode.childNodes[endOffset - 1])) {4618 endNode = endNode.childNodes[endOffset - 1];4619 endOffset = getNodeLength(endNode);4620 // "Otherwise, if end offset is zero and end node's parent is in the4621 // same editing host, set end offset to end node's index, then set end4622 // node to its parent."4623 } else if (endOffset == 04624 && inSameEditingHost(endNode, endNode.parentNode)) {4625 endOffset = getNodeIndex(endNode);4626 endNode = endNode.parentNode;4627 // "Otherwise, if end node is a Text node and its parent's resolved4628 // value for "white-space" is neither "pre" nor "pre-wrap" and end4629 // offset is end node's length and the last code unit of end node's4630 // data is a space (0x0020) and end node precedes a line break:"4631 } else if (endNode.nodeType == Node.TEXT_NODE4632 && ["pre", "pre-wrap"].indexOf(getComputedStyle(endNode.parentNode).whiteSpace) == -14633 && endOffset == getNodeLength(endNode)4634 && endNode.data[endNode.data.length - 1] == " "4635 && precedesLineBreak(endNode)) {4636 // "Subtract one from end offset."4637 endOffset--;4638 // "Subtract one from length."4639 length--;4640 // "Call deleteData(end offset, 1) on end node."4641 endNode.deleteData(endOffset, 1);4642 // "Otherwise, break from this loop."4643 } else {4644 break;4645 }4646 }4647 }4648 // "Let replacement whitespace be the canonical space sequence of length4649 // length. non-breaking start is true if start offset is zero and start4650 // node follows a line break, and false otherwise. non-breaking end is true4651 // if end offset is end node's length and end node precedes a line break,4652 // and false otherwise."4653 var replacementWhitespace = canonicalSpaceSequence(length,4654 startOffset == 0 && followsLineBreak(startNode),4655 endOffset == getNodeLength(endNode) && precedesLineBreak(endNode));4656 // "While (start node, start offset) is before (end node, end offset):"4657 while (getPosition(startNode, startOffset, endNode, endOffset) == "before") {4658 // "If start node has a child with index start offset, set start node4659 // to that child, then set start offset to zero."4660 if (startOffset < startNode.childNodes.length) {4661 startNode = startNode.childNodes[startOffset];4662 startOffset = 0;4663 // "Otherwise, if start node is not a Text node or if start offset is4664 // start node's length, set start offset to one plus start node's4665 // index, then set start node to its parent."4666 } else if (startNode.nodeType != Node.TEXT_NODE4667 || startOffset == getNodeLength(startNode)) {4668 startOffset = 1 + getNodeIndex(startNode);4669 startNode = startNode.parentNode;4670 // "Otherwise:"4671 } else {4672 // "Remove the first element from replacement whitespace, and let4673 // element be that element."4674 var element = replacementWhitespace[0];4675 replacementWhitespace = replacementWhitespace.slice(1);4676 // "If element is not the same as the start offsetth element of4677 // start node's data:"4678 if (element != startNode.data[startOffset]) {4679 // "Call insertData(start offset, element) on start node."4680 startNode.insertData(startOffset, element);4681 // "Call deleteData(start offset + 1, 1) on start node."4682 startNode.deleteData(startOffset + 1, 1);4683 }4684 // "Add one to start offset."4685 startOffset++;4686 }4687 }4688}4689//@}4690///// Indenting and outdenting /////4691//@{4692function indentNodes(nodeList) {4693 // "If node list is empty, do nothing and abort these steps."4694 if (!nodeList.length) {4695 return;4696 }4697 // "Let first node be the first member of node list."4698 var firstNode = nodeList[0];4699 // "If first node's parent is an ol or ul:"4700 if (isHtmlElement(firstNode.parentNode, ["OL", "UL"])) {4701 // "Let tag be the local name of the parent of first node."4702 var tag = firstNode.parentNode.tagName;4703 // "Wrap node list, with sibling criteria returning true for an HTML4704 // element with local name tag and false otherwise, and new parent4705 // instructions returning the result of calling createElement(tag) on4706 // the ownerDocument of first node."4707 wrap(nodeList,4708 function(node) { return isHtmlElement(node, tag) },4709 function() { return firstNode.ownerDocument.createElement(tag) });4710 // "Abort these steps."4711 return;4712 }4713 // "Wrap node list, with sibling criteria returning true for a simple4714 // indentation element and false otherwise, and new parent instructions4715 // returning the result of calling createElement("blockquote") on the4716 // ownerDocument of first node. Let new parent be the result."4717 var newParent = wrap(nodeList,4718 function(node) { return isSimpleIndentationElement(node) },4719 function() { return firstNode.ownerDocument.createElement("blockquote") });4720 // "Fix disallowed ancestors of new parent."4721 fixDisallowedAncestors(newParent);4722}4723function outdentNode(node) {4724 // "If node is not editable, abort these steps."4725 if (!isEditable(node)) {4726 return;4727 }4728 // "If node is a simple indentation element, remove node, preserving its4729 // descendants. Then abort these steps."4730 if (isSimpleIndentationElement(node)) {4731 removePreservingDescendants(node);4732 return;4733 }4734 // "If node is an indentation element:"4735 if (isIndentationElement(node)) {4736 // "Unset the dir attribute of node, if any."4737 node.removeAttribute("dir");4738 // "Unset the margin, padding, and border CSS properties of node."4739 node.style.margin = "";4740 node.style.padding = "";4741 node.style.border = "";4742 if (node.getAttribute("style") == ""4743 // Crazy WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=685514744 || node.getAttribute("style") == "border-width: initial; border-color: initial; ") {4745 node.removeAttribute("style");4746 }4747 // "Set the tag name of node to "div"."4748 setTagName(node, "div");4749 // "Abort these steps."4750 return;4751 }4752 // "Let current ancestor be node's parent."4753 var currentAncestor = node.parentNode;4754 // "Let ancestor list be a list of nodes, initially empty."4755 var ancestorList = [];4756 // "While current ancestor is an editable Element that is neither a simple4757 // indentation element nor an ol nor a ul, append current ancestor to4758 // ancestor list and then set current ancestor to its parent."4759 while (isEditable(currentAncestor)4760 && currentAncestor.nodeType == Node.ELEMENT_NODE4761 && !isSimpleIndentationElement(currentAncestor)4762 && !isHtmlElement(currentAncestor, ["ol", "ul"])) {4763 ancestorList.push(currentAncestor);4764 currentAncestor = currentAncestor.parentNode;4765 }4766 // "If current ancestor is not an editable simple indentation element:"4767 if (!isEditable(currentAncestor)4768 || !isSimpleIndentationElement(currentAncestor)) {4769 // "Let current ancestor be node's parent."4770 currentAncestor = node.parentNode;4771 // "Let ancestor list be the empty list."4772 ancestorList = [];4773 // "While current ancestor is an editable Element that is neither an4774 // indentation element nor an ol nor a ul, append current ancestor to4775 // ancestor list and then set current ancestor to its parent."4776 while (isEditable(currentAncestor)4777 && currentAncestor.nodeType == Node.ELEMENT_NODE4778 && !isIndentationElement(currentAncestor)4779 && !isHtmlElement(currentAncestor, ["ol", "ul"])) {4780 ancestorList.push(currentAncestor);4781 currentAncestor = currentAncestor.parentNode;4782 }4783 }4784 // "If node is an ol or ul and current ancestor is not an editable4785 // indentation element:"4786 if (isHtmlElement(node, ["OL", "UL"])4787 && (!isEditable(currentAncestor)4788 || !isIndentationElement(currentAncestor))) {4789 // "Unset the reversed, start, and type attributes of node, if any are4790 // set."4791 node.removeAttribute("reversed");4792 node.removeAttribute("start");4793 node.removeAttribute("type");4794 // "Let children be the children of node."4795 var children = [].slice.call(node.childNodes);4796 // "If node has attributes, and its parent is not an ol or ul, set the4797 // tag name of node to "div"."4798 if (node.attributes.length4799 && !isHtmlElement(node.parentNode, ["OL", "UL"])) {4800 setTagName(node, "div");4801 // "Otherwise:"4802 } else {4803 // "Record the values of node's children, and let values be the4804 // result."4805 var values = recordValues([].slice.call(node.childNodes));4806 // "Remove node, preserving its descendants."4807 removePreservingDescendants(node);4808 // "Restore the values from values."4809 restoreValues(values);4810 }4811 // "Fix disallowed ancestors of each member of children."4812 for (var i = 0; i < children.length; i++) {4813 fixDisallowedAncestors(children[i]);4814 }4815 // "Abort these steps."4816 return;4817 }4818 // "If current ancestor is not an editable indentation element, abort these4819 // steps."4820 if (!isEditable(currentAncestor)4821 || !isIndentationElement(currentAncestor)) {4822 return;4823 }4824 // "Append current ancestor to ancestor list."4825 ancestorList.push(currentAncestor);4826 // "Let original ancestor be current ancestor."4827 var originalAncestor = currentAncestor;4828 // "While ancestor list is not empty:"4829 while (ancestorList.length) {4830 // "Let current ancestor be the last member of ancestor list."4831 //4832 // "Remove the last member of ancestor list."4833 currentAncestor = ancestorList.pop();4834 // "Let target be the child of current ancestor that is equal to either4835 // node or the last member of ancestor list."4836 var target = node.parentNode == currentAncestor4837 ? node4838 : ancestorList[ancestorList.length - 1];4839 // "If target is an inline node that is not a br, and its nextSibling4840 // is a br, remove target's nextSibling from its parent."4841 if (isInlineNode(target)4842 && !isHtmlElement(target, "BR")4843 && isHtmlElement(target.nextSibling, "BR")) {4844 target.parentNode.removeChild(target.nextSibling);4845 }4846 // "Let preceding siblings be the preceding siblings of target, and let4847 // following siblings be the following siblings of target."4848 var precedingSiblings = [].slice.call(currentAncestor.childNodes, 0, getNodeIndex(target));4849 var followingSiblings = [].slice.call(currentAncestor.childNodes, 1 + getNodeIndex(target));4850 // "Indent preceding siblings."4851 indentNodes(precedingSiblings);4852 // "Indent following siblings."4853 indentNodes(followingSiblings);4854 }4855 // "Outdent original ancestor."4856 outdentNode(originalAncestor);4857}4858//@}4859///// Toggling lists /////4860//@{4861function toggleLists(tagName) {4862 // "Record current overrides, and let overrides be the result."4863 var overrides = recordCurrentOverrides();4864 // "Let mode be "disable" if the selection's list state is tag name, and4865 // "enable" otherwise."4866 var mode = getSelectionListState() == tagName ? "disable" : "enable";4867 var range = getActiveRange();4868 tagName = tagName.toUpperCase();4869 // "Let other tag name be "ol" if tag name is "ul", and "ul" if tag name is4870 // "ol"."4871 var otherTagName = tagName == "OL" ? "UL" : "OL";4872 // "Let items be a list of all lis that are ancestor containers of the4873 // range's start and/or end node."4874 //4875 // It's annoying to get this in tree order using functional stuff without4876 // doing getDescendants(document), which is slow, so I do it imperatively.4877 var items = [];4878 (function(){4879 for (4880 var ancestorContainer = range.endContainer;4881 ancestorContainer != range.commonAncestorContainer;4882 ancestorContainer = ancestorContainer.parentNode4883 ) {4884 if (isHtmlElement(ancestorContainer, "li")) {4885 items.unshift(ancestorContainer);4886 }4887 }4888 for (4889 var ancestorContainer = range.startContainer;4890 ancestorContainer;4891 ancestorContainer = ancestorContainer.parentNode4892 ) {4893 if (isHtmlElement(ancestorContainer, "li")) {4894 items.unshift(ancestorContainer);4895 }4896 }4897 })();4898 // "For each item in items, normalize sublists of item."4899 items.forEach(normalizeSublists);4900 // "Block-extend the range, and let new range be the result."4901 var newRange = blockExtend(range);4902 // "If mode is "enable", then let lists to convert consist of every4903 // editable HTML element with local name other tag name that is contained4904 // in new range, and for every list in lists to convert:"4905 if (mode == "enable") {4906 getAllContainedNodes(newRange, function(node) {4907 return isEditable(node)4908 && isHtmlElement(node, otherTagName);4909 }).forEach(function(list) {4910 // "If list's previousSibling or nextSibling is an editable HTML4911 // element with local name tag name:"4912 if ((isEditable(list.previousSibling) && isHtmlElement(list.previousSibling, tagName))4913 || (isEditable(list.nextSibling) && isHtmlElement(list.nextSibling, tagName))) {4914 // "Let children be list's children."4915 var children = [].slice.call(list.childNodes);4916 // "Record the values of children, and let values be the4917 // result."4918 var values = recordValues(children);4919 // "Split the parent of children."4920 splitParent(children);4921 // "Wrap children, with sibling criteria returning true for an4922 // HTML element with local name tag name and false otherwise."4923 wrap(children, function(node) { return isHtmlElement(node, tagName) });4924 // "Restore the values from values."4925 restoreValues(values);4926 // "Otherwise, set the tag name of list to tag name."4927 } else {4928 setTagName(list, tagName);4929 }4930 });4931 }4932 // "Let node list be a list of nodes, initially empty."4933 //4934 // "For each node node contained in new range, if node is editable; the4935 // last member of node list (if any) is not an ancestor of node; node4936 // is not an indentation element; and either node is an ol or ul, or its4937 // parent is an ol or ul, or it is an allowed child of "li"; then append4938 // node to node list."4939 var nodeList = getContainedNodes(newRange, function(node) {4940 return isEditable(node)4941 && !isIndentationElement(node)4942 && (isHtmlElement(node, ["OL", "UL"])4943 || isHtmlElement(node.parentNode, ["OL", "UL"])4944 || isAllowedChild(node, "li"));4945 });4946 // "If mode is "enable", remove from node list any ol or ul whose parent is4947 // not also an ol or ul."4948 if (mode == "enable") {4949 nodeList = nodeList.filter(function(node) {4950 return !isHtmlElement(node, ["ol", "ul"])4951 || isHtmlElement(node.parentNode, ["ol", "ul"]);4952 });4953 }4954 // "If mode is "disable", then while node list is not empty:"4955 if (mode == "disable") {4956 while (nodeList.length) {4957 // "Let sublist be an empty list of nodes."4958 var sublist = [];4959 // "Remove the first member from node list and append it to4960 // sublist."4961 sublist.push(nodeList.shift());4962 // "If the first member of sublist is an HTML element with local4963 // name tag name, outdent it and continue this loop from the4964 // beginning."4965 if (isHtmlElement(sublist[0], tagName)) {4966 outdentNode(sublist[0]);4967 continue;4968 }4969 // "While node list is not empty, and the first member of node list4970 // is the nextSibling of the last member of sublist and is not an4971 // HTML element with local name tag name, remove the first member4972 // from node list and append it to sublist."4973 while (nodeList.length4974 && nodeList[0] == sublist[sublist.length - 1].nextSibling4975 && !isHtmlElement(nodeList[0], tagName)) {4976 sublist.push(nodeList.shift());4977 }4978 // "Record the values of sublist, and let values be the result."4979 var values = recordValues(sublist);4980 // "Split the parent of sublist."4981 splitParent(sublist);4982 // "Fix disallowed ancestors of each member of sublist."4983 for (var i = 0; i < sublist.length; i++) {4984 fixDisallowedAncestors(sublist[i]);4985 }4986 // "Restore the values from values."4987 restoreValues(values);4988 }4989 // "Otherwise, while node list is not empty:"4990 } else {4991 while (nodeList.length) {4992 // "Let sublist be an empty list of nodes."4993 var sublist = [];4994 // "While either sublist is empty, or node list is not empty and4995 // its first member is the nextSibling of sublist's last member:"4996 while (!sublist.length4997 || (nodeList.length4998 && nodeList[0] == sublist[sublist.length - 1].nextSibling)) {4999 // "If node list's first member is a p or div, set the tag name5000 // of node list's first member to "li", and append the result5001 // to sublist. Remove the first member from node list."5002 if (isHtmlElement(nodeList[0], ["p", "div"])) {5003 sublist.push(setTagName(nodeList[0], "li"));5004 nodeList.shift();5005 // "Otherwise, if the first member of node list is an li or ol5006 // or ul, remove it from node list and append it to sublist."5007 } else if (isHtmlElement(nodeList[0], ["li", "ol", "ul"])) {5008 sublist.push(nodeList.shift());5009 // "Otherwise:"5010 } else {5011 // "Let nodes to wrap be a list of nodes, initially empty."5012 var nodesToWrap = [];5013 // "While nodes to wrap is empty, or node list is not empty5014 // and its first member is the nextSibling of nodes to5015 // wrap's last member and the first member of node list is5016 // an inline node and the last member of nodes to wrap is5017 // an inline node other than a br, remove the first member5018 // from node list and append it to nodes to wrap."5019 while (!nodesToWrap.length5020 || (nodeList.length5021 && nodeList[0] == nodesToWrap[nodesToWrap.length - 1].nextSibling5022 && isInlineNode(nodeList[0])5023 && isInlineNode(nodesToWrap[nodesToWrap.length - 1])5024 && !isHtmlElement(nodesToWrap[nodesToWrap.length - 1], "br"))) {5025 nodesToWrap.push(nodeList.shift());5026 }5027 // "Wrap nodes to wrap, with new parent instructions5028 // returning the result of calling createElement("li") on5029 // the context object. Append the result to sublist."5030 sublist.push(wrap(nodesToWrap,5031 undefined,5032 function() { return document.createElement("li") }));5033 }5034 }5035 // "If sublist's first member's parent is an HTML element with5036 // local name tag name, or if every member of sublist is an ol or5037 // ul, continue this loop from the beginning."5038 if (isHtmlElement(sublist[0].parentNode, tagName)5039 || sublist.every(function(node) { return isHtmlElement(node, ["ol", "ul"]) })) {5040 continue;5041 }5042 // "If sublist's first member's parent is an HTML element with5043 // local name other tag name:"5044 if (isHtmlElement(sublist[0].parentNode, otherTagName)) {5045 // "Record the values of sublist, and let values be the5046 // result."5047 var values = recordValues(sublist);5048 // "Split the parent of sublist."5049 splitParent(sublist);5050 // "Wrap sublist, with sibling criteria returning true for an5051 // HTML element with local name tag name and false otherwise,5052 // and new parent instructions returning the result of calling5053 // createElement(tag name) on the context object."5054 wrap(sublist,5055 function(node) { return isHtmlElement(node, tagName) },5056 function() { return document.createElement(tagName) });5057 // "Restore the values from values."5058 restoreValues(values);5059 // "Continue this loop from the beginning."5060 continue;5061 }5062 // "Wrap sublist, with sibling criteria returning true for an HTML5063 // element with local name tag name and false otherwise, and new5064 // parent instructions being the following:"5065 // . . .5066 // "Fix disallowed ancestors of the previous step's result."5067 fixDisallowedAncestors(wrap(sublist,5068 function(node) { return isHtmlElement(node, tagName) },5069 function() {5070 // "If sublist's first member's parent is not an editable5071 // simple indentation element, or sublist's first member's5072 // parent's previousSibling is not an editable HTML element5073 // with local name tag name, call createElement(tag name)5074 // on the context object and return the result."5075 if (!isEditable(sublist[0].parentNode)5076 || !isSimpleIndentationElement(sublist[0].parentNode)5077 || !isEditable(sublist[0].parentNode.previousSibling)5078 || !isHtmlElement(sublist[0].parentNode.previousSibling, tagName)) {5079 return document.createElement(tagName);5080 }5081 // "Let list be sublist's first member's parent's5082 // previousSibling."5083 var list = sublist[0].parentNode.previousSibling;5084 // "Normalize sublists of list's lastChild."5085 normalizeSublists(list.lastChild);5086 // "If list's lastChild is not an editable HTML element5087 // with local name tag name, call createElement(tag name)5088 // on the context object, and append the result as the last5089 // child of list."5090 if (!isEditable(list.lastChild)5091 || !isHtmlElement(list.lastChild, tagName)) {5092 list.appendChild(document.createElement(tagName));5093 }5094 // "Return the last child of list."5095 return list.lastChild;5096 }5097 ));5098 }5099 }5100 // "Restore states and values from overrides."5101 restoreStatesAndValues(overrides);5102}5103//@}5104///// Justifying the selection /////5105//@{5106function justifySelection(alignment) {5107 // "Record current overrides, and let overrides be the result."5108 var overrides = recordCurrentOverrides();5109 // "Block-extend the active range, and let new range be the result."5110 var newRange = blockExtend(globalRange);5111 // "Let element list be a list of all editable Elements contained in new5112 // range that either has an attribute in the HTML namespace whose local5113 // name is "align", or has a style attribute that sets "text-align", or is5114 // a center."5115 var elementList = getAllContainedNodes(newRange, function(node) {5116 return node.nodeType == Node.ELEMENT_NODE5117 && isEditable(node)5118 // Ignoring namespaces here5119 && (5120 node.hasAttribute("align")5121 || node.style.textAlign != ""5122 || isHtmlElement(node, "center")5123 );5124 });5125 // "For each element in element list:"5126 for (var i = 0; i < elementList.length; i++) {5127 var element = elementList[i];5128 // "If element has an attribute in the HTML namespace whose local name5129 // is "align", remove that attribute."5130 element.removeAttribute("align");5131 // "Unset the CSS property "text-align" on element, if it's set by a5132 // style attribute."5133 element.style.textAlign = "";5134 if (element.getAttribute("style") == "") {5135 element.removeAttribute("style");5136 }5137 // "If element is a div or span or center with no attributes, remove5138 // it, preserving its descendants."5139 if (isHtmlElement(element, ["div", "span", "center"])5140 && !element.attributes.length) {5141 removePreservingDescendants(element);5142 }5143 // "If element is a center with one or more attributes, set the tag5144 // name of element to "div"."5145 if (isHtmlElement(element, "center")5146 && element.attributes.length) {5147 setTagName(element, "div");5148 }5149 }5150 // "Block-extend the active range, and let new range be the result."5151 newRange = blockExtend(globalRange);5152 // "Let node list be a list of nodes, initially empty."5153 var nodeList = [];5154 // "For each node node contained in new range, append node to node list if5155 // the last member of node list (if any) is not an ancestor of node; node5156 // is editable; node is an allowed child of "div"; and node's alignment5157 // value is not alignment."5158 nodeList = getContainedNodes(newRange, function(node) {5159 return isEditable(node)5160 && isAllowedChild(node, "div")5161 && getAlignmentValue(node) != alignment;5162 });5163 // "While node list is not empty:"5164 while (nodeList.length) {5165 // "Let sublist be a list of nodes, initially empty."5166 var sublist = [];5167 // "Remove the first member of node list and append it to sublist."5168 sublist.push(nodeList.shift());5169 // "While node list is not empty, and the first member of node list is5170 // the nextSibling of the last member of sublist, remove the first5171 // member of node list and append it to sublist."5172 while (nodeList.length5173 && nodeList[0] == sublist[sublist.length - 1].nextSibling) {5174 sublist.push(nodeList.shift());5175 }5176 // "Wrap sublist. Sibling criteria returns true for any div that has5177 // one or both of the following two attributes and no other attributes,5178 // and false otherwise:"5179 //5180 // * "An align attribute whose value is an ASCII case-insensitive5181 // match for alignment.5182 // * "A style attribute which sets exactly one CSS property5183 // (including unrecognized or invalid attributes), which is5184 // "text-align", which is set to alignment.5185 //5186 // "New parent instructions are to call createElement("div") on the5187 // context object, then set its CSS property "text-align" to alignment5188 // and return the result."5189 wrap(sublist,5190 function(node) {5191 return isHtmlElement(node, "div")5192 && [].every.call(node.attributes, function(attr) {5193 return (attr.name == "align" && attr.value.toLowerCase() == alignment)5194 || (attr.name == "style" && node.style.length == 1 && node.style.textAlign == alignment);5195 });5196 },5197 function() {5198 var newParent = document.createElement("div");5199 newParent.setAttribute("style", "text-align: " + alignment);5200 return newParent;5201 }5202 );5203 }5204 // "Restore states and values from overrides."5205 restoreStatesAndValues(overrides);5206}5207//@}5208///// Automatic linking /////5209//@{5210// "An autolinkable URL is a string of the following form:"5211var autolinkableUrlRegexp =5212 // "Either a string matching the scheme pattern from RFC 3986 section 3.15213 // followed by the literal string ://, or the literal string mailto:;5214 // followed by"5215 //5216 // From the RFC: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )5217 "([a-zA-Z][a-zA-Z0-9+.-]*://|mailto:)"5218 // "Zero or more characters other than space characters; followed by"5219 + "[^ \t\n\f\r]*"5220 // "A character that is not one of the ASCII characters !"'(),-.:;<>[]`{}."5221 + "[^!\"'(),\\-.:;<>[\\]`{}]";5222// "A valid e-mail address is a string that matches the ABNF production 1*(5223// atext / "." ) "@" ldh-str *( "." ldh-str ) where atext is defined in RFC5224// 5322 section 3.2.3, and ldh-str is defined in RFC 1034 section 3.5."5225//5226// atext: ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" /5227// "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"5228//5229//<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>5230//<let-dig-hyp> ::= <let-dig> | "-"5231//<let-dig> ::= <letter> | <digit>5232var validEmailRegexp =5233 "[a-zA-Z0-9!#$%&'*+\\-/=?^_`{|}~.]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*";5234function autolink(node, endOffset) {5235 // "While (node, end offset)'s previous equivalent point is not null, set5236 // it to its previous equivalent point."5237 while (getPreviousEquivalentPoint(node, endOffset)) {5238 var prev = getPreviousEquivalentPoint(node, endOffset);5239 node = prev[0];5240 endOffset = prev[1];5241 }5242 // "If node is not a Text node, or has an a ancestor, do nothing and abort5243 // these steps."5244 if (node.nodeType != Node.TEXT_NODE5245 || getAncestors(node).some(function(ancestor) { return isHtmlElement(ancestor, "a") })) {5246 return;5247 }5248 // "Let search be the largest substring of node's data whose end is end5249 // offset and that contains no space characters."5250 var search = /[^ \t\n\f\r]*$/.exec(node.substringData(0, endOffset))[0];5251 // "If some substring of search is an autolinkable URL:"5252 if (new RegExp(autolinkableUrlRegexp).test(search)) {...

Full Screen

Full Screen

implementation.js

Source:implementation.js Github

copy

Full Screen

...3251 }3252 3253 return null;3254}3255function getPreviousEquivalentPoint(node, offset) {3256 3257 if (getNodeLength(node) == 0) {3258 return null;3259 }3260 3261 3262 if (offset == 03263 && node.parentNode3264 && isInlineNode(node)) {3265 return [node.parentNode, getNodeIndex(node)];3266 }3267 3268 3269 3270 if (0 <= offset - 13271 && offset - 1 < node.childNodes.length3272 && getNodeLength(node.childNodes[offset - 1]) != 03273 && isInlineNode(node.childNodes[offset - 1])) {3274 return [node.childNodes[offset - 1], getNodeLength(node.childNodes[offset - 1])];3275 }3276 3277 return null;3278}3279function getFirstEquivalentPoint(node, offset) {3280 3281 3282 var prev;3283 while (prev = getPreviousEquivalentPoint(node, offset)) {3284 node = prev[0];3285 offset = prev[1];3286 }3287 3288 return [node, offset];3289}3290function getLastEquivalentPoint(node, offset) {3291 3292 3293 var next;3294 while (next = getNextEquivalentPoint(node, offset)) {3295 node = next[0];3296 offset = next[1];3297 }3298 3299 return [node, offset];3300}3301function isBlockStartPoint(node, offset) {3302 return (!node.parentNode && offset == 0)3303 || (0 <= offset - 13304 && offset - 1 < node.childNodes.length3305 && isVisible(node.childNodes[offset - 1])3306 && (isBlockNode(node.childNodes[offset - 1])3307 || isHtmlElement(node.childNodes[offset - 1], "br")));3308}3309function isBlockEndPoint(node, offset) {3310 return (!node.parentNode && offset == getNodeLength(node))3311 || (offset < node.childNodes.length3312 && isVisible(node.childNodes[offset])3313 && isBlockNode(node.childNodes[offset]));3314}3315function isBlockBoundaryPoint(node, offset) {3316 return isBlockStartPoint(node, offset)3317 || isBlockEndPoint(node, offset);3318}3319function blockExtend(range) {3320 3321 3322 var startNode = range.startContainer;3323 var startOffset = range.startOffset;3324 var endNode = range.endContainer;3325 var endOffset = range.endOffset;3326 3327 3328 3329 var liAncestors = getAncestors(startNode).concat(startNode)3330 .filter(function(ancestor) { return isHtmlElement(ancestor, "li") })3331 .slice(-1);3332 if (liAncestors.length) {3333 startOffset = getNodeIndex(liAncestors[0]);3334 startNode = liAncestors[0].parentNode;3335 }3336 3337 3338 if (!isBlockStartPoint(startNode, startOffset)) do {3339 3340 3341 if (startOffset == 0) {3342 startOffset = getNodeIndex(startNode);3343 startNode = startNode.parentNode;3344 3345 } else {3346 startOffset--;3347 }3348 3349 3350 } while (!isBlockBoundaryPoint(startNode, startOffset));3351 3352 3353 while (startOffset == 03354 && startNode.parentNode) {3355 startOffset = getNodeIndex(startNode);3356 startNode = startNode.parentNode;3357 }3358 3359 3360 3361 var liAncestors = getAncestors(endNode).concat(endNode)3362 .filter(function(ancestor) { return isHtmlElement(ancestor, "li") })3363 .slice(-1);3364 if (liAncestors.length) {3365 endOffset = 1 + getNodeIndex(liAncestors[0]);3366 endNode = liAncestors[0].parentNode;3367 }3368 3369 3370 if (!isBlockEndPoint(endNode, endOffset)) do {3371 3372 3373 if (endOffset == getNodeLength(endNode)) {3374 endOffset = 1 + getNodeIndex(endNode);3375 endNode = endNode.parentNode;3376 3377 } else {3378 endOffset++;3379 }3380 3381 3382 } while (!isBlockBoundaryPoint(endNode, endOffset));3383 3384 3385 3386 while (endOffset == getNodeLength(endNode)3387 && endNode.parentNode) {3388 endOffset = 1 + getNodeIndex(endNode);3389 endNode = endNode.parentNode;3390 }3391 3392 3393 var newRange = startNode.ownerDocument.createRange();3394 newRange.setStart(startNode, startOffset);3395 newRange.setEnd(endNode, endOffset);3396 3397 return newRange;3398}3399function followsLineBreak(node) {3400 3401 var offset = 0;3402 3403 while (!isBlockBoundaryPoint(node, offset)) {3404 3405 3406 if (0 <= offset - 13407 && offset - 1 < node.childNodes.length3408 && isVisible(node.childNodes[offset - 1])) {3409 return false;3410 }3411 3412 3413 if (offset == 03414 || !node.hasChildNodes()) {3415 offset = getNodeIndex(node);3416 node = node.parentNode;3417 3418 3419 } else {3420 node = node.childNodes[offset - 1];3421 offset = getNodeLength(node);3422 }3423 }3424 3425 return true;3426}3427function precedesLineBreak(node) {3428 3429 var offset = getNodeLength(node);3430 3431 while (!isBlockBoundaryPoint(node, offset)) {3432 3433 if (offset < node.childNodes.length3434 && isVisible(node.childNodes[offset])) {3435 return false;3436 }3437 3438 3439 if (offset == getNodeLength(node)3440 || !node.hasChildNodes()) {3441 offset = 1 + getNodeIndex(node);3442 node = node.parentNode;3443 3444 3445 } else {3446 node = node.childNodes[offset];3447 offset = 0;3448 }3449 }3450 3451 return true;3452}3453function recordCurrentOverrides() {3454 3455 3456 var overrides = [];3457 3458 3459 if (getValueOverride("createlink") !== undefined) {3460 overrides.push(["createlink", getValueOverride("createlink")]);3461 }3462 3463 3464 3465 3466 ["bold", "italic", "strikethrough", "subscript", "superscript",3467 "underline"].forEach(function(command) {3468 if (getStateOverride(command) !== undefined) {3469 overrides.push([command, getStateOverride(command)]);3470 }3471 });3472 3473 3474 3475 ["fontname", "fontsize", "forecolor",3476 "hilitecolor"].forEach(function(command) {3477 if (getValueOverride(command) !== undefined) {3478 overrides.push([command, getValueOverride(command)]);3479 }3480 });3481 3482 return overrides;3483}3484function recordCurrentStatesAndValues() {3485 3486 3487 var overrides = [];3488 3489 3490 var node = getAllEffectivelyContainedNodes(getActiveRange())3491 .filter(isFormattableNode)[0];3492 3493 if (!node) {3494 return overrides;3495 }3496 3497 3498 overrides.push(["createlink", getEffectiveCommandValue(node, "createlink")]);3499 3500 3501 3502 3503 3504 ["bold", "italic", "strikethrough", "subscript", "superscript",3505 "underline"].forEach(function(command) {3506 if (commands[command].inlineCommandActivatedValues3507 .indexOf(getEffectiveCommandValue(node, command)) != -1) {3508 overrides.push([command, true]);3509 } else {3510 overrides.push([command, false]);3511 }3512 });3513 3514 3515 ["fontname", "fontsize", "forecolor", "hilitecolor"].forEach(function(command) {3516 overrides.push([command, commands[command].value()]);3517 });3518 3519 3520 overrides.push(["fontsize", getEffectiveCommandValue(node, "fontsize")]);3521 3522 return overrides;3523}3524function restoreStatesAndValues(overrides) {3525 3526 3527 var node = getAllEffectivelyContainedNodes(getActiveRange())3528 .filter(isFormattableNode)[0];3529 3530 3531 if (node) {3532 for (var i = 0; i < overrides.length; i++) {3533 var command = overrides[i][0];3534 var override = overrides[i][1];3535 3536 3537 3538 if (typeof override == "boolean"3539 && myQueryCommandState(command) != override) {3540 commands[command].action("");3541 3542 3543 3544 3545 } else if (typeof override == "string"3546 && command != "createlink"3547 && command != "fontsize"3548 && !areEquivalentValues(command, myQueryCommandValue(command), override)) {3549 commands[command].action(override);3550 3551 3552 3553 3554 3555 3556 } else if (typeof override == "string"3557 && command == "createlink"3558 && (3559 (3560 getValueOverride("createlink") !== undefined3561 && getValueOverride("createlink") !== override3562 ) || (3563 getValueOverride("createlink") === undefined3564 && getEffectiveCommandValue(node, "createlink") !== override3565 )3566 )) {3567 commands.createlink.action(override);3568 3569 3570 3571 3572 3573 } else if (typeof override == "string"3574 && command == "fontsize"3575 && (3576 (3577 getValueOverride("fontsize") !== undefined3578 && getValueOverride("fontsize") !== override3579 ) || (3580 getValueOverride("fontsize") === undefined3581 && !areLooselyEquivalentValues(command, getEffectiveCommandValue(node, "fontsize"), override)3582 )3583 )) {3584 3585 3586 override = getLegacyFontSize(override);3587 3588 3589 commands.fontsize.action(override);3590 3591 } else {3592 continue;3593 }3594 3595 3596 node = getAllEffectivelyContainedNodes(getActiveRange())3597 .filter(isFormattableNode)[0]3598 || node;3599 }3600 3601 } else {3602 for (var i = 0; i < overrides.length; i++) {3603 var command = overrides[i][0];3604 var override = overrides[i][1];3605 3606 3607 if (typeof override == "boolean") {3608 setStateOverride(command, override);3609 }3610 3611 3612 if (typeof override == "string") {3613 setValueOverride(command, override);3614 }3615 }3616 }3617}3618function deleteSelection(flags) {3619 if (flags === undefined) {3620 flags = {};3621 }3622 var blockMerging = "blockMerging" in flags ? Boolean(flags.blockMerging) : true;3623 var stripWrappers = "stripWrappers" in flags ? Boolean(flags.stripWrappers) : true;3624 var direction = "direction" in flags ? flags.direction : "forward";3625 3626 if (!getActiveRange()) {3627 return;3628 }3629 3630 canonicalizeWhitespace(getActiveRange().startContainer, getActiveRange().startOffset);3631 3632 canonicalizeWhitespace(getActiveRange().endContainer, getActiveRange().endOffset);3633 3634 3635 var start = getLastEquivalentPoint(getActiveRange().startContainer, getActiveRange().startOffset);3636 var startNode = start[0];3637 var startOffset = start[1];3638 3639 3640 var end = getFirstEquivalentPoint(getActiveRange().endContainer, getActiveRange().endOffset);3641 var endNode = end[0];3642 var endOffset = end[1];3643 3644 if (getPosition(endNode, endOffset, startNode, startOffset) !== "after") {3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 if (direction == "forward") {3656 if (getSelection().rangeCount) {3657 getSelection().collapseToStart();3658 }3659 getActiveRange().collapse(true);3660 3661 } else {3662 getSelection().collapseToEnd();3663 getActiveRange().collapse(false);3664 }3665 3666 return;3667 }3668 3669 3670 if (startNode.nodeType == Node.TEXT_NODE3671 && startOffset == 0) {3672 startOffset = getNodeIndex(startNode);3673 startNode = startNode.parentNode;3674 }3675 3676 3677 if (endNode.nodeType == Node.TEXT_NODE3678 && endOffset == getNodeLength(endNode)) {3679 endOffset = 1 + getNodeIndex(endNode);3680 endNode = endNode.parentNode;3681 }3682 3683 3684 getSelection().collapse(startNode, startOffset);3685 getActiveRange().setStart(startNode, startOffset);3686 3687 getSelection().extend(endNode, endOffset);3688 getActiveRange().setEnd(endNode, endOffset);3689 3690 var startBlock = getActiveRange().startContainer;3691 3692 3693 while (inSameEditingHost(startBlock, startBlock.parentNode)3694 && isInlineNode(startBlock)) {3695 startBlock = startBlock.parentNode;3696 }3697 3698 3699 3700 if ((!isBlockNode(startBlock) && !isEditingHost(startBlock))3701 || !isAllowedChild("span", startBlock)3702 || isHtmlElement(startBlock, ["td", "th"])) {3703 startBlock = null;3704 }3705 3706 var endBlock = getActiveRange().endContainer;3707 3708 3709 while (inSameEditingHost(endBlock, endBlock.parentNode)3710 && isInlineNode(endBlock)) {3711 endBlock = endBlock.parentNode;3712 }3713 3714 3715 3716 if ((!isBlockNode(endBlock) && !isEditingHost(endBlock))3717 || !isAllowedChild("span", endBlock)3718 || isHtmlElement(endBlock, ["td", "th"])) {3719 endBlock = null;3720 }3721 3722 var overrides = recordCurrentStatesAndValues();3723 3724 3725 if (startNode == endNode3726 && isEditable(startNode)3727 && startNode.nodeType == Node.TEXT_NODE) {3728 3729 3730 startNode.deleteData(startOffset, endOffset - startOffset);3731 3732 3733 canonicalizeWhitespace(startNode, startOffset, false);3734 3735 3736 if (direction == "forward") {3737 if (getSelection().rangeCount) {3738 getSelection().collapseToStart();3739 }3740 getActiveRange().collapse(true);3741 3742 } else {3743 getSelection().collapseToEnd();3744 getActiveRange().collapse(false);3745 }3746 3747 restoreStatesAndValues(overrides);3748 3749 return;3750 }3751 3752 3753 3754 if (isEditable(startNode)3755 && startNode.nodeType == Node.TEXT_NODE) {3756 startNode.deleteData(startOffset, getNodeLength(startNode) - startOffset);3757 }3758 3759 3760 3761 3762 3763 var nodeList = getContainedNodes(getActiveRange(),3764 function(node) {3765 return isEditable(node)3766 && !isHtmlElement(node, ["thead", "tbody", "tfoot", "tr", "th", "td"]);3767 }3768 );3769 3770 for (var i = 0; i < nodeList.length; i++) {3771 var node = nodeList[i];3772 3773 var parent_ = node.parentNode;3774 3775 parent_.removeChild(node);3776 3777 3778 3779 if (![].some.call(getBlockNodeOf(parent_).childNodes, isVisible)3780 && (isEditable(parent_) || isEditingHost(parent_))) {3781 parent_.appendChild(document.createElement("br"));3782 }3783 3784 3785 3786 3787 if (stripWrappers3788 || (!isAncestor(parent_, startNode) && parent_ != startNode)) {3789 while (isEditable(parent_)3790 && isInlineNode(parent_)3791 && getNodeLength(parent_) == 0) {3792 var grandparent = parent_.parentNode;3793 grandparent.removeChild(parent_);3794 parent_ = grandparent;3795 }3796 }3797 }3798 3799 3800 if (isEditable(endNode)3801 && endNode.nodeType == Node.TEXT_NODE) {3802 endNode.deleteData(0, endOffset);3803 }3804 3805 3806 canonicalizeWhitespace(getActiveRange().startContainer, getActiveRange().startOffset, false);3807 3808 3809 canonicalizeWhitespace(getActiveRange().endContainer, getActiveRange().endOffset, false);3810 3811 3812 3813 if (!blockMerging3814 || !startBlock3815 || !endBlock3816 || !inSameEditingHost(startBlock, endBlock)3817 || startBlock == endBlock) {3818 3819 3820 if (direction == "forward") {3821 if (getSelection().rangeCount) {3822 getSelection().collapseToStart();3823 }3824 getActiveRange().collapse(true);3825 3826 } else {3827 if (getSelection().rangeCount) {3828 getSelection().collapseToEnd();3829 }3830 getActiveRange().collapse(false);3831 }3832 3833 restoreStatesAndValues(overrides);3834 3835 return;3836 }3837 3838 3839 if (startBlock.children.length == 13840 && isCollapsedBlockProp(startBlock.firstChild)) {3841 startBlock.removeChild(startBlock.firstChild);3842 }3843 3844 if (isAncestor(startBlock, endBlock)) {3845 3846 var referenceNode = endBlock;3847 3848 3849 while (referenceNode.parentNode != startBlock) {3850 referenceNode = referenceNode.parentNode;3851 }3852 3853 3854 3855 getSelection().collapse(startBlock, getNodeIndex(referenceNode));3856 getActiveRange().setStart(startBlock, getNodeIndex(referenceNode));3857 getActiveRange().collapse(true);3858 3859 if (!endBlock.hasChildNodes()) {3860 3861 3862 3863 3864 while (isEditable(endBlock)3865 && endBlock.parentNode.childNodes.length == 13866 && endBlock.parentNode != startBlock) {3867 var parent_ = endBlock;3868 parent_.removeChild(endBlock);3869 endBlock = parent_;3870 }3871 3872 3873 3874 3875 if (isEditable(endBlock)3876 && !isInlineNode(endBlock)3877 && isInlineNode(endBlock.previousSibling)3878 && isInlineNode(endBlock.nextSibling)) {3879 endBlock.parentNode.insertBefore(document.createElement("br"), endBlock.nextSibling);3880 }3881 3882 if (isEditable(endBlock)) {3883 endBlock.parentNode.removeChild(endBlock);3884 }3885 3886 restoreStatesAndValues(overrides);3887 3888 return;3889 }3890 3891 3892 if (!isInlineNode(endBlock.firstChild)) {3893 restoreStatesAndValues(overrides);3894 return;3895 }3896 3897 var children = [];3898 3899 children.push(endBlock.firstChild);3900 3901 3902 3903 while (!isHtmlElement(children[children.length - 1], "br")3904 && isInlineNode(children[children.length - 1].nextSibling)) {3905 children.push(children[children.length - 1].nextSibling);3906 }3907 3908 var values = recordValues(children);3909 3910 3911 while (children[0].parentNode != startBlock) {3912 splitParent(children);3913 }3914 3915 3916 if (isEditable(children[0].previousSibling)3917 && isHtmlElement(children[0].previousSibling, "br")) {3918 children[0].parentNode.removeChild(children[0].previousSibling);3919 }3920 3921 } else if (isDescendant(startBlock, endBlock)) {3922 3923 3924 getSelection().collapse(startBlock, getNodeLength(startBlock));3925 getActiveRange().setStart(startBlock, getNodeLength(startBlock));3926 getActiveRange().collapse(true);3927 3928 var referenceNode = startBlock;3929 3930 3931 while (referenceNode.parentNode != endBlock) {3932 referenceNode = referenceNode.parentNode;3933 }3934 3935 3936 if (isInlineNode(referenceNode.nextSibling)3937 && isHtmlElement(startBlock.lastChild, "br")) {3938 startBlock.removeChild(startBlock.lastChild);3939 }3940 3941 var nodesToMove = [];3942 3943 3944 if (referenceNode.nextSibling3945 && !isBlockNode(referenceNode.nextSibling)) {3946 nodesToMove.push(referenceNode.nextSibling);3947 }3948 3949 3950 3951 if (nodesToMove.length3952 && !isHtmlElement(nodesToMove[nodesToMove.length - 1], "br")3953 && nodesToMove[nodesToMove.length - 1].nextSibling3954 && !isBlockNode(nodesToMove[nodesToMove.length - 1].nextSibling)) {3955 nodesToMove.push(nodesToMove[nodesToMove.length - 1].nextSibling);3956 }3957 3958 var values = recordValues(nodesToMove);3959 3960 3961 nodesToMove.forEach(function(node) {3962 movePreservingRanges(node, startBlock, -1);3963 });3964 3965 } else {3966 3967 3968 getSelection().collapse(startBlock, getNodeLength(startBlock));3969 getActiveRange().setStart(startBlock, getNodeLength(startBlock));3970 getActiveRange().collapse(true);3971 3972 3973 if (isInlineNode(endBlock.firstChild)3974 && isHtmlElement(startBlock.lastChild, "br")) {3975 startBlock.removeChild(startBlock.lastChild);3976 }3977 3978 3979 var values = recordValues([].slice.call(endBlock.childNodes));3980 3981 3982 while (endBlock.hasChildNodes()) {3983 movePreservingRanges(endBlock.firstChild, startBlock, -1);3984 }3985 3986 3987 3988 while (!endBlock.hasChildNodes()) {3989 var parent_ = endBlock.parentNode;3990 parent_.removeChild(endBlock);3991 endBlock = parent_;3992 }3993 }3994 3995 var ancestor = startBlock;3996 3997 3998 3999 4000 while (getInclusiveAncestors(ancestor).some(function(node) {4001 return inSameEditingHost(ancestor, node)4002 && (4003 (isHtmlElement(node, "ol") && isHtmlElement(node.nextSibling, "ol"))4004 || (isHtmlElement(node, "ul") && isHtmlElement(node.nextSibling, "ul"))4005 ) && inSameEditingHost(ancestor, node.nextSibling);4006 })) {4007 4008 4009 4010 while (!(4011 isHtmlElement(ancestor, "ol")4012 && isHtmlElement(ancestor.nextSibling, "ol")4013 && inSameEditingHost(ancestor, ancestor.nextSibling)4014 ) && !(4015 isHtmlElement(ancestor, "ul")4016 && isHtmlElement(ancestor.nextSibling, "ul")4017 && inSameEditingHost(ancestor, ancestor.nextSibling)4018 )) {4019 ancestor = ancestor.parentNode;4020 }4021 4022 4023 4024 while (ancestor.nextSibling.hasChildNodes()) {4025 movePreservingRanges(ancestor.nextSibling.firstChild, ancestor, -1);4026 }4027 4028 ancestor.parentNode.removeChild(ancestor.nextSibling);4029 }4030 4031 restoreValues(values);4032 4033 4034 if (!startBlock.hasChildNodes()) {4035 startBlock.appendChild(document.createElement("br"));4036 }4037 4038 removeExtraneousLineBreaksAtTheEndOf(startBlock);4039 4040 restoreStatesAndValues(overrides);4041}4042function splitParent(nodeList) {4043 4044 var originalParent = nodeList[0].parentNode;4045 4046 4047 if (!isEditable(originalParent)4048 || !originalParent.parentNode) {4049 return;4050 }4051 4052 4053 if (nodeList.indexOf(originalParent.firstChild) != -1) {4054 removeExtraneousLineBreaksBefore(originalParent);4055 }4056 4057 4058 4059 var followsLineBreak_ = nodeList.indexOf(originalParent.firstChild) != -14060 && followsLineBreak(originalParent);4061 4062 4063 4064 var precedesLineBreak_ = nodeList.indexOf(originalParent.lastChild) != -14065 && precedesLineBreak(originalParent);4066 4067 4068 if (nodeList.indexOf(originalParent.firstChild) == -14069 && nodeList.indexOf(originalParent.lastChild) != -1) {4070 4071 4072 4073 for (var i = nodeList.length - 1; i >= 0; i--) {4074 movePreservingRanges(nodeList[i], originalParent.parentNode, 1 + getNodeIndex(originalParent));4075 }4076 4077 4078 4079 4080 if (precedesLineBreak_4081 && !precedesLineBreak(nodeList[nodeList.length - 1])) {4082 nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);4083 }4084 4085 removeExtraneousLineBreaksAtTheEndOf(originalParent);4086 4087 return;4088 }4089 4090 if (nodeList.indexOf(originalParent.firstChild) == -1) {4091 4092 4093 var clonedParent = originalParent.cloneNode(false);4094 4095 originalParent.removeAttribute("id");4096 4097 4098 originalParent.parentNode.insertBefore(clonedParent, originalParent);4099 4100 4101 4102 while (nodeList[0].previousSibling) {4103 movePreservingRanges(originalParent.firstChild, clonedParent, clonedParent.childNodes.length);4104 }4105 }4106 4107 4108 for (var i = 0; i < nodeList.length; i++) {4109 movePreservingRanges(nodeList[i], originalParent.parentNode, getNodeIndex(originalParent));4110 }4111 4112 4113 4114 if (followsLineBreak_4115 && !followsLineBreak(nodeList[0])) {4116 nodeList[0].parentNode.insertBefore(document.createElement("br"), nodeList[0]);4117 }4118 4119 4120 4121 4122 if (isInlineNode(nodeList[nodeList.length - 1])4123 && !isHtmlElement(nodeList[nodeList.length - 1], "br")4124 && isHtmlElement(originalParent.firstChild, "br")4125 && !isInlineNode(originalParent)) {4126 originalParent.removeChild(originalParent.firstChild);4127 }4128 4129 if (!originalParent.hasChildNodes()) {4130 4131 originalParent.parentNode.removeChild(originalParent);4132 4133 4134 4135 4136 if (precedesLineBreak_4137 && !precedesLineBreak(nodeList[nodeList.length - 1])) {4138 nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);4139 }4140 4141 } else {4142 removeExtraneousLineBreaksBefore(originalParent);4143 }4144 4145 4146 4147 if (!nodeList[nodeList.length - 1].nextSibling4148 && nodeList[nodeList.length - 1].parentNode) {4149 removeExtraneousLineBreaksAtTheEndOf(nodeList[nodeList.length - 1].parentNode);4150 }4151}4152function removePreservingDescendants(node) {4153 if (node.hasChildNodes()) {4154 splitParent([].slice.call(node.childNodes));4155 } else {4156 node.parentNode.removeChild(node);4157 }4158}4159function canonicalSpaceSequence(n, nonBreakingStart, nonBreakingEnd) {4160 4161 if (n == 0) {4162 return "";4163 }4164 4165 4166 if (n == 1 && !nonBreakingStart && !nonBreakingEnd) {4167 return " ";4168 }4169 4170 if (n == 1) {4171 return "\xa0";4172 }4173 4174 var buffer = "";4175 4176 4177 var repeatedPair;4178 if (nonBreakingStart) {4179 repeatedPair = "\xa0 ";4180 } else {4181 repeatedPair = " \xa0";4182 }4183 4184 4185 while (n > 3) {4186 buffer += repeatedPair;4187 n -= 2;4188 }4189 4190 4191 if (n == 3) {4192 buffer +=4193 !nonBreakingStart && !nonBreakingEnd ? " \xa0 "4194 : nonBreakingStart && !nonBreakingEnd ? "\xa0\xa0 "4195 : !nonBreakingStart && nonBreakingEnd ? " \xa0\xa0"4196 : nonBreakingStart && nonBreakingEnd ? "\xa0 \xa0"4197 : "impossible";4198 4199 4200 } else {4201 buffer +=4202 !nonBreakingStart && !nonBreakingEnd ? "\xa0 "4203 : nonBreakingStart && !nonBreakingEnd ? "\xa0 "4204 : !nonBreakingStart && nonBreakingEnd ? " \xa0"4205 : nonBreakingStart && nonBreakingEnd ? "\xa0\xa0"4206 : "impossible";4207 }4208 4209 return buffer;4210}4211function canonicalizeWhitespace(node, offset, fixCollapsedSpace) {4212 if (fixCollapsedSpace === undefined) {4213 4214 4215 fixCollapsedSpace = true;4216 }4217 4218 if (!isEditable(node) && !isEditingHost(node)) {4219 return;4220 }4221 4222 var startNode = node;4223 var startOffset = offset;4224 4225 while (true) {4226 4227 4228 4229 if (0 <= startOffset - 14230 && inSameEditingHost(startNode, startNode.childNodes[startOffset - 1])) {4231 startNode = startNode.childNodes[startOffset - 1];4232 startOffset = getNodeLength(startNode);4233 4234 4235 4236 4237 } else if (startOffset == 04238 && !followsLineBreak(startNode)4239 && inSameEditingHost(startNode, startNode.parentNode)) {4240 startOffset = getNodeIndex(startNode);4241 startNode = startNode.parentNode;4242 4243 4244 4245 4246 4247 } else if (startNode.nodeType == Node.TEXT_NODE4248 && ["pre", "pre-wrap"].indexOf(getComputedStyle(startNode.parentNode).whiteSpace) == -14249 && startOffset != 04250 && /[ \xa0]/.test(startNode.data[startOffset - 1])) {4251 startOffset--;4252 4253 } else {4254 break;4255 }4256 }4257 4258 var endNode = startNode;4259 var endOffset = startOffset;4260 4261 var length = 0;4262 4263 4264 var collapseSpaces = startOffset == 0 && followsLineBreak(startNode);4265 4266 while (true) {4267 4268 4269 if (endOffset < endNode.childNodes.length4270 && inSameEditingHost(endNode, endNode.childNodes[endOffset])) {4271 endNode = endNode.childNodes[endOffset];4272 endOffset = 0;4273 4274 4275 4276 4277 } else if (endOffset == getNodeLength(endNode)4278 && !precedesLineBreak(endNode)4279 && inSameEditingHost(endNode, endNode.parentNode)) {4280 endOffset = 1 + getNodeIndex(endNode);4281 endNode = endNode.parentNode;4282 4283 4284 4285 4286 } else if (endNode.nodeType == Node.TEXT_NODE4287 && ["pre", "pre-wrap"].indexOf(getComputedStyle(endNode.parentNode).whiteSpace) == -14288 && endOffset != getNodeLength(endNode)4289 && /[ \xa0]/.test(endNode.data[endOffset])) {4290 4291 4292 4293 4294 if (fixCollapsedSpace4295 && collapseSpaces4296 && " " == endNode.data[endOffset]) {4297 endNode.deleteData(endOffset, 1);4298 continue;4299 }4300 4301 4302 collapseSpaces = " " == endNode.data[endOffset];4303 4304 endOffset++;4305 4306 length++;4307 4308 } else {4309 break;4310 }4311 }4312 4313 4314 if (fixCollapsedSpace) {4315 while (getPosition(startNode, startOffset, endNode, endOffset) == "before") {4316 4317 4318 4319 if (0 <= endOffset - 14320 && endOffset - 1 < endNode.childNodes.length4321 && inSameEditingHost(endNode, endNode.childNodes[endOffset - 1])) {4322 endNode = endNode.childNodes[endOffset - 1];4323 endOffset = getNodeLength(endNode);4324 4325 4326 4327 } else if (endOffset == 04328 && inSameEditingHost(endNode, endNode.parentNode)) {4329 endOffset = getNodeIndex(endNode);4330 endNode = endNode.parentNode;4331 4332 4333 4334 4335 } else if (endNode.nodeType == Node.TEXT_NODE4336 && ["pre", "pre-wrap"].indexOf(getComputedStyle(endNode.parentNode).whiteSpace) == -14337 && endOffset == getNodeLength(endNode)4338 && endNode.data[endNode.data.length - 1] == " "4339 && precedesLineBreak(endNode)) {4340 4341 endOffset--;4342 4343 length--;4344 4345 endNode.deleteData(endOffset, 1);4346 4347 } else {4348 break;4349 }4350 }4351 }4352 4353 4354 4355 4356 4357 var replacementWhitespace = canonicalSpaceSequence(length,4358 startOffset == 0 && followsLineBreak(startNode),4359 endOffset == getNodeLength(endNode) && precedesLineBreak(endNode));4360 4361 while (getPosition(startNode, startOffset, endNode, endOffset) == "before") {4362 4363 4364 if (startOffset < startNode.childNodes.length) {4365 startNode = startNode.childNodes[startOffset];4366 startOffset = 0;4367 4368 4369 4370 } else if (startNode.nodeType != Node.TEXT_NODE4371 || startOffset == getNodeLength(startNode)) {4372 startOffset = 1 + getNodeIndex(startNode);4373 startNode = startNode.parentNode;4374 4375 } else {4376 4377 4378 var element = replacementWhitespace[0];4379 replacementWhitespace = replacementWhitespace.slice(1);4380 4381 4382 if (element != startNode.data[startOffset]) {4383 4384 startNode.insertData(startOffset, element);4385 4386 startNode.deleteData(startOffset + 1, 1);4387 }4388 4389 startOffset++;4390 }4391 }4392}4393function indentNodes(nodeList) {4394 4395 if (!nodeList.length) {4396 return;4397 }4398 4399 var firstNode = nodeList[0];4400 4401 if (isHtmlElement(firstNode.parentNode, ["OL", "UL"])) {4402 4403 var tag = firstNode.parentNode.tagName;4404 4405 4406 4407 4408 wrap(nodeList,4409 function(node) { return isHtmlElement(node, tag) },4410 function() { return firstNode.ownerDocument.createElement(tag) });4411 4412 return;4413 }4414 4415 4416 4417 4418 var newParent = wrap(nodeList,4419 function(node) { return isSimpleIndentationElement(node) },4420 function() { return firstNode.ownerDocument.createElement("blockquote") });4421 4422 fixDisallowedAncestors(newParent);4423}4424function outdentNode(node) {4425 4426 if (!isEditable(node)) {4427 return;4428 }4429 4430 4431 if (isSimpleIndentationElement(node)) {4432 removePreservingDescendants(node);4433 return;4434 }4435 4436 if (isIndentationElement(node)) {4437 4438 node.removeAttribute("dir");4439 4440 node.style.margin = "";4441 node.style.padding = "";4442 node.style.border = "";4443 if (node.getAttribute("style") == ""4444 4445 || node.getAttribute("style") == "border-width: initial; border-color: initial; ") {4446 node.removeAttribute("style");4447 }4448 4449 setTagName(node, "div");4450 4451 return;4452 }4453 4454 var currentAncestor = node.parentNode;4455 4456 var ancestorList = [];4457 4458 4459 4460 while (isEditable(currentAncestor)4461 && currentAncestor.nodeType == Node.ELEMENT_NODE4462 && !isSimpleIndentationElement(currentAncestor)4463 && !isHtmlElement(currentAncestor, ["ol", "ul"])) {4464 ancestorList.push(currentAncestor);4465 currentAncestor = currentAncestor.parentNode;4466 }4467 4468 if (!isEditable(currentAncestor)4469 || !isSimpleIndentationElement(currentAncestor)) {4470 4471 currentAncestor = node.parentNode;4472 4473 ancestorList = [];4474 4475 4476 4477 while (isEditable(currentAncestor)4478 && currentAncestor.nodeType == Node.ELEMENT_NODE4479 && !isIndentationElement(currentAncestor)4480 && !isHtmlElement(currentAncestor, ["ol", "ul"])) {4481 ancestorList.push(currentAncestor);4482 currentAncestor = currentAncestor.parentNode;4483 }4484 }4485 4486 4487 if (isHtmlElement(node, ["OL", "UL"])4488 && (!isEditable(currentAncestor)4489 || !isIndentationElement(currentAncestor))) {4490 4491 4492 node.removeAttribute("reversed");4493 node.removeAttribute("start");4494 node.removeAttribute("type");4495 4496 var children = [].slice.call(node.childNodes);4497 4498 4499 if (node.attributes.length4500 && !isHtmlElement(node.parentNode, ["OL", "UL"])) {4501 setTagName(node, "div");4502 4503 } else {4504 4505 4506 var values = recordValues([].slice.call(node.childNodes));4507 4508 removePreservingDescendants(node);4509 4510 restoreValues(values);4511 }4512 4513 for (var i = 0; i < children.length; i++) {4514 fixDisallowedAncestors(children[i]);4515 }4516 4517 return;4518 }4519 4520 4521 if (!isEditable(currentAncestor)4522 || !isIndentationElement(currentAncestor)) {4523 return;4524 }4525 4526 ancestorList.push(currentAncestor);4527 4528 var originalAncestor = currentAncestor;4529 4530 while (ancestorList.length) {4531 4532 4533 4534 currentAncestor = ancestorList.pop();4535 4536 4537 var target = node.parentNode == currentAncestor4538 ? node4539 : ancestorList[ancestorList.length - 1];4540 4541 4542 if (isInlineNode(target)4543 && !isHtmlElement(target, "BR")4544 && isHtmlElement(target.nextSibling, "BR")) {4545 target.parentNode.removeChild(target.nextSibling);4546 }4547 4548 4549 var precedingSiblings = [].slice.call(currentAncestor.childNodes, 0, getNodeIndex(target));4550 var followingSiblings = [].slice.call(currentAncestor.childNodes, 1 + getNodeIndex(target));4551 4552 indentNodes(precedingSiblings);4553 4554 indentNodes(followingSiblings);4555 }4556 4557 outdentNode(originalAncestor);4558}4559function toggleLists(tagName) {4560 4561 4562 var mode = getSelectionListState() == tagName ? "disable" : "enable";4563 var range = getActiveRange();4564 tagName = tagName.toUpperCase();4565 4566 4567 var otherTagName = tagName == "OL" ? "UL" : "OL";4568 4569 4570 4571 4572 4573 var items = [];4574 (function(){4575 for (4576 var ancestorContainer = range.endContainer;4577 ancestorContainer != range.commonAncestorContainer;4578 ancestorContainer = ancestorContainer.parentNode4579 ) {4580 if (isHtmlElement(ancestorContainer, "li")) {4581 items.unshift(ancestorContainer);4582 }4583 }4584 for (4585 var ancestorContainer = range.startContainer;4586 ancestorContainer;4587 ancestorContainer = ancestorContainer.parentNode4588 ) {4589 if (isHtmlElement(ancestorContainer, "li")) {4590 items.unshift(ancestorContainer);4591 }4592 }4593 })();4594 4595 items.forEach(normalizeSublists);4596 4597 var newRange = blockExtend(range);4598 4599 4600 4601 if (mode == "enable") {4602 getAllContainedNodes(newRange, function(node) {4603 return isEditable(node)4604 && isHtmlElement(node, otherTagName);4605 }).forEach(function(list) {4606 4607 4608 if ((isEditable(list.previousSibling) && isHtmlElement(list.previousSibling, tagName))4609 || (isEditable(list.nextSibling) && isHtmlElement(list.nextSibling, tagName))) {4610 4611 var children = [].slice.call(list.childNodes);4612 4613 4614 var values = recordValues(children);4615 4616 splitParent(children);4617 4618 4619 wrap(children, function(node) { return isHtmlElement(node, tagName) });4620 4621 restoreValues(values);4622 4623 } else {4624 setTagName(list, tagName);4625 }4626 });4627 }4628 4629 4630 4631 4632 4633 4634 4635 var nodeList = getContainedNodes(newRange, function(node) {4636 return isEditable(node)4637 && !isIndentationElement(node)4638 && (isHtmlElement(node, ["OL", "UL"])4639 || isHtmlElement(node.parentNode, ["OL", "UL"])4640 || isAllowedChild(node, "li"));4641 });4642 4643 4644 if (mode == "enable") {4645 nodeList = nodeList.filter(function(node) {4646 return !isHtmlElement(node, ["ol", "ul"])4647 || isHtmlElement(node.parentNode, ["ol", "ul"]);4648 });4649 }4650 4651 if (mode == "disable") {4652 while (nodeList.length) {4653 4654 var sublist = [];4655 4656 4657 sublist.push(nodeList.shift());4658 4659 4660 4661 if (isHtmlElement(sublist[0], tagName)) {4662 outdentNode(sublist[0]);4663 continue;4664 }4665 4666 4667 4668 4669 while (nodeList.length4670 && nodeList[0] == sublist[sublist.length - 1].nextSibling4671 && !isHtmlElement(nodeList[0], tagName)) {4672 sublist.push(nodeList.shift());4673 }4674 4675 var values = recordValues(sublist);4676 4677 splitParent(sublist);4678 4679 for (var i = 0; i < sublist.length; i++) {4680 fixDisallowedAncestors(sublist[i]);4681 }4682 4683 restoreValues(values);4684 }4685 4686 } else {4687 while (nodeList.length) {4688 4689 var sublist = [];4690 4691 4692 while (!sublist.length4693 || (nodeList.length4694 && nodeList[0] == sublist[sublist.length - 1].nextSibling)) {4695 4696 4697 4698 if (isHtmlElement(nodeList[0], ["p", "div"])) {4699 sublist.push(setTagName(nodeList[0], "li"));4700 nodeList.shift();4701 4702 4703 } else if (isHtmlElement(nodeList[0], ["li", "ol", "ul"])) {4704 sublist.push(nodeList.shift());4705 4706 } else {4707 4708 var nodesToWrap = [];4709 4710 4711 4712 4713 4714 4715 while (!nodesToWrap.length4716 || (nodeList.length4717 && nodeList[0] == nodesToWrap[nodesToWrap.length - 1].nextSibling4718 && isInlineNode(nodeList[0])4719 && isInlineNode(nodesToWrap[nodesToWrap.length - 1])4720 && !isHtmlElement(nodesToWrap[nodesToWrap.length - 1], "br"))) {4721 nodesToWrap.push(nodeList.shift());4722 }4723 4724 4725 4726 sublist.push(wrap(nodesToWrap,4727 undefined,4728 function() { return document.createElement("li") }));4729 }4730 }4731 4732 4733 4734 if (isHtmlElement(sublist[0].parentNode, tagName)4735 || sublist.every(function(node) { return isHtmlElement(node, ["ol", "ul"]) })) {4736 continue;4737 }4738 4739 4740 if (isHtmlElement(sublist[0].parentNode, otherTagName)) {4741 4742 4743 var values = recordValues(sublist);4744 4745 splitParent(sublist);4746 4747 4748 4749 4750 wrap(sublist,4751 function(node) { return isHtmlElement(node, tagName) },4752 function() { return document.createElement(tagName) });4753 4754 restoreValues(values);4755 4756 continue;4757 }4758 4759 4760 4761 4762 4763 fixDisallowedAncestors(wrap(sublist,4764 function(node) { return isHtmlElement(node, tagName) },4765 function() {4766 4767 4768 4769 4770 4771 if (!isEditable(sublist[0].parentNode)4772 || !isSimpleIndentationElement(sublist[0].parentNode)4773 || !isEditable(sublist[0].parentNode.previousSibling)4774 || !isHtmlElement(sublist[0].parentNode.previousSibling, tagName)) {4775 return document.createElement(tagName);4776 }4777 4778 4779 var list = sublist[0].parentNode.previousSibling;4780 4781 normalizeSublists(list.lastChild);4782 4783 4784 4785 4786 if (!isEditable(list.lastChild)4787 || !isHtmlElement(list.lastChild, tagName)) {4788 list.appendChild(document.createElement(tagName));4789 }4790 4791 return list.lastChild;4792 }4793 ));4794 }4795 }4796}4797function justifySelection(alignment) {4798 4799 var newRange = blockExtend(globalRange);4800 4801 4802 4803 4804 var elementList = getAllContainedNodes(newRange, function(node) {4805 return node.nodeType == Node.ELEMENT_NODE4806 && isEditable(node)4807 4808 && (4809 node.hasAttribute("align")4810 || node.style.textAlign != ""4811 || isHtmlElement(node, "center")4812 );4813 });4814 4815 for (var i = 0; i < elementList.length; i++) {4816 var element = elementList[i];4817 4818 4819 element.removeAttribute("align");4820 4821 4822 element.style.textAlign = "";4823 if (element.getAttribute("style") == "") {4824 element.removeAttribute("style");4825 }4826 4827 4828 if (isHtmlElement(element, ["div", "span", "center"])4829 && !element.attributes.length) {4830 removePreservingDescendants(element);4831 }4832 4833 4834 if (isHtmlElement(element, "center")4835 && element.attributes.length) {4836 setTagName(element, "div");4837 }4838 }4839 4840 newRange = blockExtend(globalRange);4841 4842 var nodeList = [];4843 4844 4845 4846 4847 nodeList = getContainedNodes(newRange, function(node) {4848 return isEditable(node)4849 && isAllowedChild(node, "div")4850 && getAlignmentValue(node) != alignment;4851 });4852 4853 while (nodeList.length) {4854 4855 var sublist = [];4856 4857 sublist.push(nodeList.shift());4858 4859 4860 4861 while (nodeList.length4862 && nodeList[0] == sublist[sublist.length - 1].nextSibling) {4863 sublist.push(nodeList.shift());4864 }4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 wrap(sublist,4879 function(node) {4880 return isHtmlElement(node, "div")4881 && [].every.call(node.attributes, function(attr) {4882 return (attr.name == "align" && attr.value.toLowerCase() == alignment)4883 || (attr.name == "style" && node.style.length == 1 && node.style.textAlign == alignment);4884 });4885 },4886 function() {4887 var newParent = document.createElement("div");4888 newParent.setAttribute("style", "text-align: " + alignment);4889 return newParent;4890 }4891 );4892 }4893}4894var autolinkableUrlRegexp =4895 4896 4897 4898 4899 4900 "([a-zA-Z][a-zA-Z0-9+.-]*://|mailto:)"4901 4902 + "[^ \t\n\f\r]*"4903 4904 + "[^!\"'(),\\-.:;<>[\\]`{}]";4905var validEmailRegexp =4906 "[a-zA-Z0-9!#$%&'*+\\-/=?^_`{|}~.]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*";4907function autolink(node, endOffset) {4908 4909 4910 while (getPreviousEquivalentPoint(node, endOffset)) {4911 var prev = getPreviousEquivalentPoint(node, endOffset);4912 node = prev[0];4913 endOffset = prev[1];4914 }4915 4916 4917 if (node.nodeType != Node.TEXT_NODE4918 || getAncestors(node).some(function(ancestor) { return isHtmlElement(ancestor, "a") })) {4919 return;4920 }4921 4922 4923 var search = /[^ \t\n\f\r]*$/.exec(node.substringData(0, endOffset))[0];4924 4925 if (new RegExp(autolinkableUrlRegexp).test(search)) {...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require("waypoint");2var wpt1 = new wpt.Waypoint();3var wpt2 = new wpt.Waypoint();4var wpt3 = new wpt.Waypoint();5var wpt4 = new wpt.Waypoint();6var wpt5 = new wpt.Waypoint();7var wpt6 = new wpt.Waypoint();8var wpt7 = new wpt.Waypoint();9wpt1.setLatitude(10);10wpt1.setLongitude(20);11wpt2.setLatitude(10);12wpt2.setLongitude(20);13wpt3.setLatitude(10);14wpt3.setLongitude(20);15wpt4.setLatitude(10);16wpt4.setLongitude(20);17wpt5.setLatitude(10);18wpt5.setLongitude(20);19wpt6.setLatitude(10);20wpt6.setLongitude(20);21wpt7.setLatitude(10);22wpt7.setLongitude(20);23var wptArr = [wpt1,wpt2,wpt3,wpt4,wpt5,wpt6,wpt7];24var wptArr1 = wpt.getPreviousEquivalentPoint(wptArr);25console.log(wptArr1);26var wpt = require("waypoint");27var wpt1 = new wpt.Waypoint();28var wpt2 = new wpt.Waypoint();29var wpt3 = new wpt.Waypoint();30var wpt4 = new wpt.Waypoint();31var wpt5 = new wpt.Waypoint();32var wpt6 = new wpt.Waypoint();33var wpt7 = new wpt.Waypoint();34wpt1.setLatitude(10);35wpt1.setLongitude(20);36wpt2.setLatitude(10);37wpt2.setLongitude(20);38wpt3.setLatitude(10);39wpt3.setLongitude(20);40wpt4.setLatitude(10);41wpt4.setLongitude(20);42wpt5.setLatitude(10);43wpt5.setLongitude(20);44wpt6.setLatitude(10);45wpt6.setLongitude(20);46wpt7.setLatitude(10);47wpt7.setLongitude(

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = new Waypoint(0,0,0);2var prevWpt = wpt.getPreviousEquivalentPoint();3prevWpt.x = 1;4prevWpt.y = 2;5prevWpt.z = 3;6wpt.x = 5;7wpt.y = 6;8wpt.z = 7;9wpt.setPreviousEquivalentPoint(prevWpt);10wpt.getPreviousEquivalentPoint().x = 8;11wpt.getPreviousEquivalentPoint().setX(9);12wpt.getPreviousEquivalentPoint().setPreviousEquivalentPoint(new Waypoint(10,11,12));13wpt.getPreviousEquivalentPoint().getPreviousEquivalentPoint().x = 13;14wpt.getPreviousEquivalentPoint().getPreviousEquivalentPoint().setX(14);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var point = wpt.getPreviousEquivalentPoint(1,2,3,4,5,6,7,8,9);3console.log(point);4var wpt = require('wpt');5var point = wpt.getPreviousEquivalentPoint(1,2);6console.log(point);7var wpt = require('wpt');8var point = wpt.getPreviousEquivalentPoint(1,2,3,4,5,6,7,8);9console.log(point);10var wpt = require('wpt');11var point = wpt.getPreviousEquivalentPoint(1,2,3,4,5,6,7,8,9,10);12console.log(point);13var wpt = require('wpt');14var point = wpt.getPreviousEquivalentPoint(1,2,3,4,5,6,7,8,9,10,11);15console.log(point);16var wpt = require('wpt');17var point = wpt.getPreviousEquivalentPoint(1,2,3,4,5,6,7,8,9,10,11,12);18console.log(point);19var wpt = require('wpt');20var point = wpt.getPreviousEquivalentPoint(1,2,3,4,5,6,7,8,9,10,11,12,13);21console.log(point);22var wpt = require('wpt');23var point = wpt.getPreviousEquivalentPoint(1,2,3,4,5,6,7,8,9,10,11,12,13,14);24console.log(point);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = new WayPoint(1,1,1);2var wpt2 = new WayPoint(1,1,1);3var wpt3 = new WayPoint(1,1,2);4var wpt = new WayPoint(1,1,1);5var wpt2 = new WayPoint(1,1,1);6var wpt3 = new WayPoint(1,1,2);7var wpt = new WayPoint(1,1,1);8var wpt2 = new WayPoint(1,1,1);9var wpt3 = new WayPoint(1,1,2);10var wpt = new WayPoint(1,1,1);11var wpt2 = new WayPoint(1,1,1);12var wpt3 = new WayPoint(1,1,2);13var wpt = new WayPoint(1,1,1);14var wpt2 = new WayPoint(1,1,1);15var wpt3 = new WayPoint(1,1,2);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = new Waypoint(0, 0, 0, 0, 0, 0, 0, 0);2var prev = wpt.getPreviousEquivalentPoint();3var route = new Route();4var wpt = new Waypoint(0, 0, 0, 0, 0, 0, 0, 0);5route.addWaypoint(wpt);6var prev = route.getPreviousEquivalentPoint();

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var point = wpt.getPreviousEquivalentPoint(2, 2, 4, 4);3var wpt = require('wpt');4var point = wpt.getPreviousEquivalentPoint(2, 2, 2, 2);5var wpt = require('wpt');6var point = wpt.getPreviousEquivalentPoint(2, 2, 2, 3);7var wpt = require('wpt');8var point = wpt.getPreviousEquivalentPoint(2, 2, 3, 2);9var wpt = require('wpt');10var point = wpt.getPreviousEquivalentPoint(2, 2, 3, 3);11var wpt = require('wpt');12var point = wpt.getPreviousEquivalentPoint(2, 2, 1, 1);13var wpt = require('wpt');14var point = wpt.getPreviousEquivalentPoint(2, 2, 1, 2);15var wpt = require('wpt');16var point = wpt.getPreviousEquivalentPoint(2, 2, 1, 3);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var previousPoint = wpt.getPreviousEquivalentPoint(10, 20, 1);3console.log(previousPoint);4var wpt = require('wpt');5var nextPoint = wpt.getNextEquivalentPoint(10, 20, 1);6console.log(nextPoint);7var wpt = require('wpt');8var point = wpt.getPointOnLine(10, 20, 30, 40, 1);9console.log(point);10var wpt = require('wpt');11var point = wpt.getPointOnCurve(10, 20, 30, 40, 50, 60, 70, 80, 1);12console.log(point);13var wpt = require('wpt');14var point = wpt.getPointOnBezierCurve(10, 20, 30, 40, 50, 60, 1);15console.log(point);16var wpt = require('wpt');17var point = wpt.getPointOnQuadraticCurve(10, 20, 30, 40, 50, 60, 1);18console.log(point);19var wpt = require('wpt');20var point = wpt.getPointOnSpline(10, 20, 30, 40, 50, 60, 70, 80, 1);21console.log(point);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = new WayPoint(1, 2);2var wpt2 = new WayPoint(2, 3);3wpt.getPreviousEquivalentPoint(wpt2);4### getPreviousEquivalentPoint(wpt)5### getPreviousPoint()6### getPreviousPointAtDistance(distance)7### getPreviousPointAtDistanceFromEnd(distance)8### getPreviousPointAtTime(time)9### getPreviousPointAtTimeFromEnd(time)10### getPreviousPointAtX(x)11### getPreviousPointAtY(y)12### getPreviousPointInDirection(direction)13### getPreviousPointInDirectionFromEnd(direction)14### getPreviousPointInDirectionFromTime(direction, time)15### getPreviousPointInDirectionFromTimeFromEnd(direction, time)16### getPreviousPointInDirectionFromX(direction, x)17### getPreviousPointInDirectionFromY(direction, y)18### getPreviousPointInDirectionFromXFromEnd(direction, x)19### getPreviousPointInDirectionFromYFromEnd(direction, y)

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful