Below are the diffs from Visual.js which include four new functions for sliding elements on/off to the left/right and two for sliding pairs of elements together, one on and one off, and one for sliding pairs of elements in a direction relative to their position in the DOM.
The diffs also include the changes I discussed in my previous post about issues with slideDown and blindDown. I have tested these on divs whose width are 100% of the browser window on both Firefox 3rc2 and Safari 3.1.1. I have not tested with any variation of IE. I also have not tested with divs with a smaller than 100% width though there's nothing to suggest it won't work right. Index: Visual.js =================================================================== --- Visual.js (revision 1383) +++ Visual.js (working copy) @@ -1431,14 +1431,16 @@ scaleContent: false, scaleX: false, scaleFrom: 0, - scaleMode: {originalHeight: s.getElementHeight(element), - originalWidth: s.getElementWidth(element)}, restoreAfterFinish: true, - afterSetupInternal: function (effect) { + beforeSetupInternal: function (effect) { elemClip = d.makeClipping(effect.element); - s.setStyle(effect.element, {height: '0px'}); s.showElement(effect.element); + effect.options.scaleMode = {originalHeight: s.getElementHeight(element), + originalWidth: s.getElementWidth(element)}; }, + afterSetupInternal: function (effect) { + s.setStyle(effect.element, {height: '0px'}); + }, afterFinishInternal: function (effect) { d.undoClipping(effect.element, elemClip); } @@ -1582,18 +1584,20 @@ scaleContent: false, scaleX: false, scaleFrom: 0, - scaleMode: {originalHeight: s.getElementHeight(element), - originalWidth: s.getElementWidth(element)}, restoreAfterFinish: true, + beforeSetupInternal: function (effect) { + elemClip = d.makeClipping(effect.element); + s.showElement(effect.element); + scaleMode = {originalHeight: s.getElementHeight(element), + originalWidth: s.getElementWidth(element)}; + }, afterSetupInternal: function (effect) { d.makePositioned(effect.element); d.makePositioned(effect.element.firstChild); if (/Opera/.test(navigator.userAgent)) { s.setStyle(effect.element, {top: ''}); } - elemClip = d.makeClipping(effect.element); s.setStyle(effect.element, {height: '0px'}); - s.showElement(effect.element); }, afterUpdateInternal: function (effect) { s.setStyle(effect.element.firstChild, @@ -1665,7 +1669,450 @@ }, options); return new MochiKit.Visual.Scale(element, 0, options); }; +/** @id MochiKit.Visual.slideOnLeft */ +MochiKit.Visual.slideOnLeft = function (element, /* optional */ options) { + /*** + Slide an element on moving from right to left. + It must have a single inner child to work correctly + + ***/ + if (!element.hasChildNodes()) { + throw "MochiKit.Visual.slideOnLeft must be used on a element with a child"; + } + var d = MochiKit.DOM; + var b = MochiKit.Base; + var s = MochiKit.Style; + var elemClip; + element = d.getElement(element); + d.removeEmptyTextNodes(element); + + /* don't want s.getElementWidth/Height, want the raw values for full restore */ + var originalStyle = { + height: element.style.height, + width: element.style.width, + left: element.style.left, + innerWidth: element.firstChild.style.width + }; + + options = b.update({ + scaleContent: false, + scaleY: false, + scaleFrom: 0, + restoreAfterFinish: true, + beforeSetupInternal: function (effect) { + elemClip = d.makeClipping(effect.element); + s.showElement(effect.element); + scaleMode = { + originalHeight: s.getElementHeight(effect.element), + originalWidth: s.getElementWidth(effect.element) + }; + }, + afterSetupInternal: function (effect) { + s.setStyle(effect.element, { + width: '0px', + left: effect.dims[1] + }); + s.setStyle(effect.element.firstChild, { + width: scaleMode.originalWidth + }); + d.makePositioned(effect.element); + d.makePositioned(effect.element.firstChild); + if (/Opera/.test(navigator.userAgent)) { + s.setStyle(effect.element, {left: ''}); + } + }, + afterUpdateInternal: function (effect) { + s.setStyle(effect.element, { + left: (effect.dims[1] - s.getElementWidth(effect.element)) + 'px' + }); + }, + afterFinishInternal: function (effect) { + d.undoClipping(effect.element, elemClip); + // IE will crash if child is undoPositioned first + if (/MSIE/.test(navigator.userAgent)) { + d.undoPositioned(effect.element); + d.undoPositioned(effect.element.firstChild); + } else { + d.undoPositioned(effect.element.firstChild); + d.undoPositioned(effect.element); + } + s.setStyle(effect.element, { + height: originalStyle.height, + width: originalStyle.width, + left: originalStyle.left + }); + s.setStyle(effect.element.firstChild, { + width: originalStyle.innerWidth + }); + } + }, options); + + return new MochiKit.Visual.Scale(element, 100, options); +} + +/** @id MochiKit.Visual.slideOnRight */ +MochiKit.Visual.slideOnRight = function (element, /* optional */ options) { + /*** + + Slide an element on moving from left to right. + It must have a single inner child to work correctly + + ***/ + if (!element.hasChildNodes()) { + throw "MochiKit.Visual.slideOnRight must be used on a element with a child"; + } + var d = MochiKit.DOM; + var b = MochiKit.Base; + var s = MochiKit.Style; + var elemClip; + element = d.getElement(element); + d.removeEmptyTextNodes(element); + + /* don't want s.getElementWidth/Height, want the raw values for full restore */ + var originalStyle = { + height: element.style.height, + width: element.style.width, + innerRight: element.firstChild.style.right, + innerWidth: element.firstChild.style.width + }; + + options = b.update({ + scaleContent: false, + scaleY: false, + scaleFrom: 0, + restoreAfterFinish: true, + beforeSetupInternal: function (effect) { + elemClip = d.makeClipping(effect.element); + s.showElement(effect.element); + scaleMode = { + originalHeight: s.getElementHeight(effect.element), + originalWidth: s.getElementWidth(effect.element) + }; + }, + afterSetupInternal: function (effect) { + s.setStyle(effect.element, {width: '0px'}); + s.setStyle(effect.element.firstChild, { + width: scaleMode.originalWidth, + right: effect.dims[1] + }); + d.makePositioned(effect.element); + d.makePositioned(effect.element.firstChild); + if (/Opera/.test(navigator.userAgent)) { + s.setStyle(effect.element, {left: ''}); + } + }, + afterUpdateInternal: function (effect) { + s.setStyle(effect.element.firstChild, { + right: (effect.dims[1] - s.getElementWidth(effect.element)) + 'px' + }); + }, + afterFinishInternal: function (effect) { + d.undoClipping(effect.element, elemClip); + // IE will crash if child is undoPositioned first + if (/MSIE/.test(navigator.userAgent)) { + d.undoPositioned(effect.element); + d.undoPositioned(effect.element.firstChild); + } else { + d.undoPositioned(effect.element.firstChild); + d.undoPositioned(effect.element); + } + s.setStyle(effect.element, { + height: originalStyle.height, + width: originalStyle.width + }); + s.setStyle(effect.element.firstChild, { + right: originalStyle.innerRight, + width: originalStyle.innerWidth + }); + } + }, options); + + return new MochiKit.Visual.Scale(element, 100, options); +} + +/** @id MochiKit.Visual.slideOffLeft */ +MochiKit.Visual.slideOffLeft = function (element, /* optional */ options) { + /*** + + Slide an element off moving from right to left. + It must have a single inner child to work correctly + + ***/ + if (!element.hasChildNodes()) { + throw "MochiKit.Visual.slideOffLeft must be used on a element with a child"; + } + var d = MochiKit.DOM; + var b = MochiKit.Base; + var s = MochiKit.Style; + var elemClip; + element = d.getElement(element); + d.removeEmptyTextNodes(element); + + /* don't want s.getElementWidth/Height, want the raw values for full restore */ + var originalStyle = { + height: element.style.height, + width: element.style.width, + right: element.style.right, + left: element.style.left, + innerRight: element.firstChild.style.right + }; + + options = b.update({ + scaleContent: false, + scaleY: false, + scaleFrom: 100, + restoreAfterFinish: true, + beforeSetupInternal: function (effect) { + elemClip = d.makeClipping(effect.element); + s.showElement(effect.element); + scaleMode = { + originalHeight: s.getElementHeight(effect.element), + originalWidth: s.getElementWidth(effect.element), + }; + }, + afterSetupInternal: function (effect) { + s.setStyle(effect.element, {left: '0px'}); + s.setStyle(effect.element.firstChild, {width: scaleMode.originalWidth}); + d.makePositioned(effect.element); + d.makePositioned(effect.element.firstChild); + if (/Opera/.test(navigator.userAgent)) { + s.setStyle(effect.element, {right: ''}); + } + }, + afterUpdateInternal: function (effect) { + s.setStyle(effect.element.firstChild, { + right: (effect.dims[1] - s.getElementWidth(effect.element)) + 'px' + }); + }, + afterFinishInternal: function (effect) { + s.hideElement(effect.element); + d.undoClipping(effect.element, elemClip); + d.undoPositioned(effect.element.firstChild); + d.undoPositioned(effect.element); + s.setStyle(effect.element, { + width: originalStyle.width, + height: originalStyle.height, + right: originalStyle.right, + left: originalStyle.left + }); + s.setStyle(effect.element.firstChild, { + right: originalStyle.innerRight + }); + } + }, options); + return new MochiKit.Visual.Scale(element, 0, options); +}; + +/** @id MochiKit.Visual.slideOffRight */ +MochiKit.Visual.slideOffRight = function (element, /* optional */ options) { + /*** + + Slide an element off moving from left to right. + It must have a single inner child to work correctly + + ***/ + if (!element.hasChildNodes()) { + throw "MochiKit.Visual.slideOffRight must be used on a element with a child"; + } + var d = MochiKit.DOM; + var b = MochiKit.Base; + var s = MochiKit.Style; + var elemClip; + element = d.getElement(element); + d.removeEmptyTextNodes(element); + + /* don't want s.getElementWidth/Height, want the raw values for full restore */ + var originalStyle = { + height: element.style.height, + width: element.style.width, + right: element.style.right, + left: element.style.left, + innerWidth: element.firstChild.style.width + }; + + options = b.update({ + scaleContent: false, + scaleY: false, + scaleFrom: 100, + restoreAfterFinish: true, + beforeSetupInternal: function (effect) { + elemClip = d.makeClipping(effect.element); + s.showElement(effect.element); + scaleMode = { + originalHeight: s.getElementHeight(effect.element), + originalWidth: s.getElementWidth(effect.element), + }; + }, + afterSetupInternal: function (effect) { + s.setStyle(effect.element, {left: '0px'}); + s.setStyle(effect.element.firstChild, {width: scaleMode.originalWidth}); + d.makePositioned(effect.element); + d.makePositioned(effect.element.firstChild); + if (/Opera/.test(navigator.userAgent)) { + s.setStyle(effect.element, {right: ''}); + } + }, + afterUpdateInternal: function (effect) { + s.setStyle(effect.element, { + left: (effect.dims[1] - s.getElementWidth(effect.element)) + 'px' + }); + }, + afterFinishInternal: function (effect) { + s.hideElement(effect.element); + d.undoClipping(effect.element, elemClip); + d.undoPositioned(effect.element.firstChild); + d.undoPositioned(effect.element); + s.setStyle(effect.element, { + width: originalStyle.width, + height: originalStyle.height, + right: originalStyle.right, + left: originalStyle.left + }); + s.setStyle(effect.element.firstChild, { + width: originalStyle.innerWidth + }); + } + }, options); + return new MochiKit.Visual.Scale(element, 0, options); +}; + +/** @id MochiKit.Visual.slidePairLeft */ +MochiKit.Visual.slidePairLeft = function (elements, /* optional */ options) { + /*** + + Slide the first element off and the second element off from right to left. + + ***/ + if (elements[0] != elements[1]) { + var d = MochiKit.DOM; + var b = MochiKit.Base; + var s = MochiKit.Style; + var v = MochiKit.Visual; + elements = [d.getElement(elements[0]), d.getElement(elements[1])]; + var parent = elements[1].parentNode; + var originalStyle = { + position: [ + elements[0].style.position, + elements[1].style.position + ], + parentWidth: parent.style.width, + parentHeight: parent.style.height + }; + options = b.update({ + beforeSetupInternal: function (effect) { + }, + afterSetupInternal: function (effect) { + s.setStyle(effect.effects[0].element.parentNode, { + width: Math.max(s.getElementWidth(effect.effects[0].element), + s.getElementWidth(effect.effects[1].element)), + height: Math.max(s.getElementHeight(effect.effects[0].element), + s.getElementHeight(effect.effects[1].element)) + }); + s.setStyle(effect.effects[0].element, {position: 'absolute'}); + s.setStyle(effect.effects[1].element, {position: 'absolute'}); + }, + afterFinishInternal: function (effect) { + s.setStyle(effect.effects[0].element, { + position: originalStyle.position[0] + }); + s.setStyle(effect.effects[1].element, { + position: originalStyle.position[1] + }); + s.setStyle(parent, { + width: originalStyle.parentWidth, + height: originalStyle.parentHeight + }); + } + }, options); + return new v.Parallel( + [v.slideOffLeft(elements[0]), v.slideOnLeft(elements[1])], + options); + } else { + return null; + } +} + +/** @id MochiKit.Visual.slidePairRight */ +MochiKit.Visual.slidePairRight = function (elements, /* optional */ options) { + /*** + + Slide the first element off and the second element off from left to right. + + ***/ + if (elements[0] != elements[1]) { + var d = MochiKit.DOM; + var b = MochiKit.Base; + var s = MochiKit.Style; + elements = [d.getElement(elements[0]), d.getElement(elements[1])]; + var parent = elements[1].parentNode; + var originalStyle = { + position: [ + elements[0].style.position, + elements[1].style.position + ], + parentWidth: parent.style.width, + parentHeight: parent.style.height + }; + options = b.update({ + beforeSetupInternal: function (effect) { + }, + afterSetupInternal: function (effect) { + s.setStyle(effect.effects[0].element.parentNode, { + width: Math.max(s.getElementWidth(effect.effects[0].element), + s.getElementWidth(effect.effects[1].element)), + height: Math.max(s.getElementHeight(effect.effects[0].element), + s.getElementHeight(effect.effects[1].element)) + }); + s.setStyle(effect.effects[0].element, {position: 'absolute'}); + s.setStyle(effect.effects[1].element, {position: 'absolute'}); + }, + afterFinishInternal: function (effect) { + s.setStyle(effect.effects[0].element, { + position: originalStyle.position[0] + }); + s.setStyle(effect.effects[1].element, { + position: originalStyle.position[1] + }); + s.setStyle(parent, { + width: originalStyle.parentWidth, + height: originalStyle.parentHeight + }); + } + }, options); + return new MochiKit.Visual.Parallel( + [slideOffRight(elements[0]), slideOnRight(elements[1])], + options); + } else { + return null; + } +} + +/** @id MochiKit.Visual.slidePairRight */ +MochiKit.Visual.slidePair = function (elements, /* optional */ options) { + /*** + + Slide the first element on and the second element off. Direction is based + on relative position of the two elements in the child node list. It assumes + both are siblings. + + ***/ + if (elements[0] != elements[1]) { + for (sibling = elements[0].nextSibling; + sibling && sibling != elements[1]; + sibling = sibling.nextSibling) { + } + if (sibling == elements[1]) { + return MochiKit.Visual.slidePairRight(elements, options); + } else { + return MochiKit.Visual.slidePairLeft(elements, options); + } + } else { + return null; + } +} + + // Bug in opera makes the TD containing this element expand for a instance // after finish /** @id MochiKit.Visual.squish */ @@ -1995,6 +2442,13 @@ "shake", "slideDown", "slideUp", + "slideOnLeft", + "slideOnRight", + "slideOffLeft", + "slideOffRight", + "slidePairLeft", + "slidePairRight", + "slidePair", "squish", "grow", "shrink", --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "MochiKit" group. To post to this group, send email to mochikit@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/mochikit?hl=en -~----------~----~----~----~------~----~------~--~---