分享一则JavaScript滚动条插件源码


Posted in Javascript onMarch 03, 2015

这是过年的时候自己写的js滚动条插件的源码,做出的效果自己并不满意,正因为做的并不满意所以回头重新巩固和深入学习js,这个插件有如下几个不太满意的地方:

内容的过度效果,可以参阅QQ客户端最近会话列表里的滚动条,它的滚动非常的平滑,简单的说就是缺少动画过渡效果。

并不算完美的兼容性,在IE6、7下的style仍然有点缺憾。

样式的不完美,例如鼠标悬浮才显示滚动条,移除后隐藏这种效果都没有写。

内部结构的混乱,需要调整内容结构。

滚动条那个图片毕竟不是美工,自己切图切的真是恶心到爆了...??/p>

总体来说还是可以看的,还是缺少一个动画。在写这个插件意识到自己的插件用到了一些比较基础的函数,于是想到把这些函数应该封装起来,最近仍然在深入学习js,把手头上这本书看完就应该着手写这个基础函数的插件了,当然,动画引擎必不可少。话不多说,源码在此(注意:本插件完整版的是有图片的,请在文末附件中下载完整的插件):

CSS

.lf_Scroll, .lf_Scroll li { padding: 0; margin: 0; list-style: none; font: 14px/24px "Helvetica Neue" ,Helvetica,Arial, 'Microsoft Yahei' ,sans-serif; outline: none; }

.lf_Scroll { cursor: pointer; width: 10px; position: absolute; right: 0; top: 0; filter: alpha(opacity=50); -moz-opacity: 0.5; -khtml-opacity: 0.5; opacity: 0.5; }

.lf_ScrollFocus { filter: alpha(opacity=100); -moz-opacity: 1; -khtml-opacity: 1; opacity: 1; }

.lfs_Top, .lfs_Center, .lfs_Bottom { background: url('ScrollBar.gif'); width: 10px; height: 10px; }

.lfs_Top { background-position: 1px 0px; }

.lfs_Center { background-position: center 0; height: 100px; }

.lfs_Bottom { background-position: -22px 0; }

/*Developers config*/

.rollDiv { height: 100%; width: 100%; overflow: hidden; position: relative; }

JavaScript

/*

* This plugin is defined on the simulation Webpage scroll bar, please insert after binding for DOM events

*

* Comment version: 1.0.0

* Author:linkfly

* Sina:为你聚焦半世纪 |  cnblogs:http://www.cnblogs.com/silin6/ | Email:linkFly6@live.com

* date:2014-02-05 02:38:35

* 

*

* Dual licensed under the MIT and GPL licenses:

* http://www.opensource.org/licenses/mit-license.php

* http://www.gnu.org/licenses/gpl.html

*

*/

(function (window, undefined) {

    //配置参数信息

    var config = {

        auto: true,

        height: 'auto',

        width: 'auto'

    };

    var linkFlyScroll = function (dom, options) {

        /// <summary>

        ///     1: 生成模拟滚动条对象,【请在本对象工作之后再为您指定的对象绑定事件,否则您之前绑定的事件将不会进行工作】

        ///     
    1.1 - linkFlyScroll(dom) - 在指定的dom上生成滚动条对象

        ///     
    1.2 - linkFlyScroll(dom,options) - 生成滚动条对象,同时提供一系列的参数允许您自定义配置该对象的工作模型

        /// </summary>

        /// <param name="dom" type="String Or element">

        ///     传入js的dom对象,或者为string类型的该对象ID

        /// </param>

        /// <param name="options" type="Json">

        ///     自定义配置该对象的工作模型,有如下选项:

        ///     
  [可选]auto(Boolean):当内容并未达到容器的高度的时候,是否自动隐藏滚动条,默认为true(是)

        ///     
  [可选]height(Int Or String):默认单位为px,可以为int和String.值为auto则默认采用css的高度

        ///     
  [可选]width(Int Or String):默认单位为px,可以为int和String.值为auto则默认采用css的宽度

        /// </param>

        /// <returns type="linkFlyScroll" />

        if (typeof (dom) === 'string') {

            dom = document.getElementById(dom);

        }

        //没有指定dom和没有查找到有效的dom

        //linkFlyScroll("")、 linkFlyScroll(null)、linkFlyScroll(undefined)

        if (!dom || !dom.nodeType)

            return this;

        //创建容器对象

        var scrollObj = document.createElement('div');

        //深度克隆内容对象,并未包含事件,所以需要等到linkFlyScroll对象工作完毕后才可以为该dom对象绑定事件

        var cloneObj = dom.cloneNode(true);

        scrollObj.className = 'rollDiv';

        scrollObj.appendChild(cloneObj);

        //替换页面上当前对象

        dom.parentNode.replaceChild(scrollObj, dom);

        return new linkFlyScroll.prototype.init(scrollObj, options ? options : {});

    };

    linkFlyScroll.prototype.init = function (dom, options) {

        /// <summary>

        ///     1: 本对象才是真正意义上工作的对象,特殊的工作方式是因为可能存在linkFlyScroll的静态调用和实例化调用

        ///     
    1.1 - init(dom,options) - 在指定的dom上生成滚动条对象

        /// </summary>

        /// <param name="dom" type="element">

        ///     dom对象

        /// </param>

        /// <param name="options" type="Json">

        ///     自定义配置该对象的工作模型,有如下选项:

        ///     
  [可选]auto(Boolean):当内容并未达到容器的高度的时候,是否自动隐藏滚动条,默认为true(是)

        ///     
  [可选]height(Int Or String):默认单位为px,可以为int和String.值为auto则默认采用css的高度

        ///     
  [可选]width(Int Or String):默认单位为px,可以为int和String.值为auto则默认采用css的宽度

        /// </param>

        /// <returns type="linkFlyScroll" />

        /*

        * 本对象包含以下属性:

        * isDrag:是否正在拖拽滚动条

        * startTop:(工作中)滚动条开始滚动位置

        * endTop:(工作中)滚动条结束滚动位置

        * topLimit:滚动条顶部极限位置

        * bottomLimit:滚动条底部极限位置

        * context:内容Dom

        * scrollRadix:滚动基数

        * target:容器Dom

        */

        //当前this对象,为防止this指针在环境中会经常改变(例如绑定事件的时候),所以将当前对象保存起来

        var currScroll = this;

        //DOMElement

        if (dom.nodeType) {

            //保存容器和内容DOM

            currScroll.target = dom;

            currScroll.context = dom.firstChild;

            //合并配置参数

            currScroll.options = tool.extend(config, options);

            if (currScroll.options.width !== 'auto') {

                dom.style.width = tool.convertValue(currScroll.options.width);

            }

            if (currScroll.options.height !== 'auto') {

                dom.style.height = tool.convertValue(currScroll.options.height);

            }

            //查找到有效的dom

            while (currScroll.context.nodeType != 1) {

                currScroll.context = currScroll.context.nextSibling;

            }

            //创建滚动条dom

            currScroll.scrollUl = document.createElement('ul');

            currScroll.scrollUl.className = 'lf_Scroll';

            currScroll.scrollUl.appendChild(tool.setClass('li', 'lfs_Top'));

            currScroll.scrollUl.appendChild(tool.setClass('li', 'lfs_Center'));

            currScroll.scrollUl.appendChild(tool.setClass('li', 'lfs_Bottom'));

            currScroll.context.style.position = 'relative';

            //先呈现在页面上才可以读取位置数据

            dom.appendChild(currScroll.scrollUl);

            this.change();

            tool.addScrollEvent(currScroll.context, function (e) {

                //绑定鼠标滚轮事件,3px滚动单位

                if (e.wheel > 0) {//滚轮向上滚动

                    var currTop = currScroll.endTop -= 3;

                    currScroll.scrollEvent.call(currScroll, currTop);

                } else {//滚轮向下滚动

                    var currTop = currScroll.endTop += 3;

                    currScroll.scrollEvent.call(currScroll, currTop);

                }

            });

            //需要处理禁止文字在拖动的时候被选中  TODO

            //鼠标点下事件,需要判断是否是左键点击,目前右键也会实现滚动  TODO

            tool.addEvent(currScroll.scrollUl, 'mousedown', function (e) {

                mouseDown.call(currScroll, e);

            });

            //追加事件,为了更好的用户体验在body上实现监听

            tool.addEvent(document.body, 'mousemove', function (e) {

                if (currScroll.isDrag) {

                    //获取当前鼠标位置

                    var position = tool.getMousePos(e);

                    //当前滚动条top位置

                    var currTop = (currScroll.endTop + position.y - currScroll.startTop);

                    //call是为了让this指针准确的指向本工作对象

                    currScroll.scrollEvent.call(currScroll, currTop);

                }

                return false;

            });

            //追加鼠标释放事件,为了准确的捕捉到释放事件在body上监听

            tool.addEvent(document.body, 'mouseup', function () {

                mouseUp.call(currScroll, []);

            });

            var mouseDown = function (e) {

                /// <summary>

                ///     1: 鼠标按下事件

                ///     
    1.1 - mouseDown(e) - 滚动条中鼠标按下滚动条事件

                /// </summary>

                /// <param name="e" type="Event">

                ///     Event对象

                /// </param>

                /// <returns type="linkFlyScroll" />

                currScroll.isDrag = true;

                //获取当前鼠标y位置

                currScroll.startTop = tool.getMousePos(e).y;

                tool.addClass(currScroll.scrollUl, 'lf_ScrollFocus');

                return false;

            };

            var mouseUp = function () {

                /// <summary>

                ///     1: 鼠标释放事件

                ///     
    1.1 - mouseUp() - 滚动条中鼠标释放滚动条事件

                /// </summary>

                /// <returns type="linkFlyScroll" />

                currScroll.isDrag = false;

                currScroll.endTop = currScroll.scrollUl.style.top ? parseInt(currScroll.scrollUl.style.top) : 0;

                tool.removeClass(currScroll.scrollUl, 'lf_ScrollFocus');

                return false;

            };

            currScroll.scrollEvent = function (currTop) {

                /// <summary>

                ///     1: 滚动事件(核心),传入需要滚动的坐标即可(滚动条top)

                ///     
    1.1 - scrollEvent(currTop) - 核心滚动事件

                /// </summary>

                /// <param name="currTop" type="Int">

                ///     滚动条顶部距离上一层容器的top值

                /// </param>

                /// <returns type="void" />

                if (currTop <= currScroll.topLimit || currTop < 0) {//顶部极限

                    currTop = currScroll.topLimit;

                } else if (currTop >= currScroll.bottomLimit) {//底部极限

                    currTop = currScroll.bottomLimit;

                }

                //滚动条偏移效果

                currScroll.scrollUl.style.top = currTop + 'px';

                var tempTop = parseInt(currScroll.context.style.top ? currScroll.context.style.top : 0);

                //debug code

                //                document.getElementById('postionInfo').innerHTML = 'currTop:' + currTop + ' 滚动基数:' + currScroll.scrollRadix + ' bottomLimit:' + currScroll.bottomLimit + ' endTop:' + currScroll.endTop + ' startTop:' + currScroll.startTop + " Y:" + currTop + " offsetTop:" + currScroll.scrollUl.offsetTop + " compute:" + (currTop * currScroll.scrollRadix * -1) + 'px';

                //text code

                //内容滚动:当前滚动条top*基数取负数

                currScroll.context.style.top = currTop * currScroll.scrollRadix * -1 + 'px';

            };

            return currScroll;

        };

    };

    linkFlyScroll.prototype.init.prototype.change = function () {

        /// <summary>

        ///     1: 滚动条内容改变函数

        ///     
    1.1 - change() - 本函数代表刷新本滚动条对象的数据,在某些情况下,内容的数据是一直在变化的,可以调用本函数对当前滚动条对象刷新数据

        /// </summary>

        /// <returns type="linkFlyScroll" />

        /*

        * linkFlyScroll包含的属性主要在本函数中初始化或重新定义:

        * isDrag:是否正在拖拽滚动条

        * startTop:(工作中)滚动条开始滚动位置

        * endTop:(工作中)滚动条结束滚动位置

        * topLimit:滚动条顶部极限位置

        * bottomLimit:滚动条底部极限位置

        * context:内容Dom

        * scrollRadix:滚动基数

        * target:容器Dom

        */

        //重置或读取一系列数据

        var currScroll = this;

        currScroll.isDrag = false,

        currScroll.startTop = 0,

        currScroll.endTop = (currScroll.scrollUl.style.top ? parseInt(currScroll.scrollUl.style.top) : 0),

        currScroll.topLimit = currScroll.target.scrollTop,

        currScroll.bottomLimit = currScroll.target.clientHeight,

        currScroll.scrollRadix = 10;

        //得出滚动条的高度:内容高度*(容器高度/内容高度=容器占内容百分比)

        var scrollPx = currScroll.target.clientHeight * (currScroll.target.clientHeight / currScroll.context.offsetHeight);

        //滚动条高度

        currScroll.scrollUl.childNodes[1].style.height = scrollPx + 'px';

        if (currScroll.context.clientHeight <= currScroll.target.clientHeight && currScroll.options.auto) {

            currScroll.scrollUl.style.display = 'none';

        } else {

            currScroll.scrollUl.style.display = 'block';

            //当滚动条显示,修正最大位置数据

            currScroll.bottomLimit -= currScroll.scrollUl.offsetHeight;

        }

        //设置滚动条滚动基数(滚动条没滚动1px内容滚动像素):(内容高度-容器高度[因为当前容器已经显示了一屏])/滚动条top(滚动条空白可滚动高度)

        currScroll.scrollRadix = (currScroll.context.offsetHeight - currScroll.target.clientHeight) / currScroll.bottomLimit;

        return currScroll;

    };

    linkFlyScroll.prototype.init.prototype.roll = function (value) {

        /// <summary>

        ///     1: 滚动条偏移方法

        ///     
    1.1 - roll(value) - 滚动条滚动方法

        /// </summary>

        /// <param name="value" type="Int">

        ///     滚动条目标滚动的百分比

        /// </param>

        /// <returns type="linkFlyScroll" />

        var currScroll = this;

        if (typeof (value) !== 'number') {

            return currScroll;

        }

        var currTop = (currScroll.bottomLimit - currScroll.topLimit) * value / 100;

        currScroll.scrollEvent(currTop);

        currScroll.endTop = currTop;

        return currScroll;

    };

    /*

    * 工具类

    */

    var tool = {

        setClass: function (element, className) {

            /// <summary>

            ///     1: 设置元素节点的class属性

            ///     
    1.1 - setClass(element,className) - 设置元素节点的class属性,如没有该节点则创建该节点,并返回修改后的节点对象

            /// </summary>

            /// <param name="element" type="Element Or String">

            ///     传入String则创建该节点,否则修改该节点

            /// </param>

            /// <param name="className" type="String">

            ///     Class Name

            /// </param>

            /// <returns type="Element" />

            if (typeof element === 'string') {

                element = document.createElement(element);

            }

            element.className = className;

            return element;

        },

        hasClass: function (element, className) {

            /// <summary>

            ///     1: 判断元素是否有class

            ///     
    1.1 - hasClass(element,className) - 判断元素是否有class,在业务中异常(基本没有该情况的发生)和有该class返回true,否则返回false

            /// </summary>

            /// <param name="element" type="Element Or String">

            ///     节点对象

            /// </param>

            /// <param name="className" type="String">

            ///     Class Name

            /// </param>

            /// <returns type="Element" />

            if (!element || element.nodeType !== 1)//让异常通过,外面不进行处理

                return true;

            var elementClassName = element.className;

            if (elementClassName.length < 1) {

                return false;

            }

            if (elementClassName == className || elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) {

                return true;

            }

            return false;

        },

        addClass: function (element, className) {

            /// <summary>

            ///     1: 为元素【追加】class

            ///     
    1.1 - addClass(element,className) - 为元素【追加】class,并返回修改后的class

            /// </summary>

            /// <param name="element" type="Element Or String">

            ///     节点对象

            /// </param>

            /// <param name="className" type="String">

            ///     Class Name

            /// </param>

            /// <returns type="Element" />

            if (!tool.hasClass(element, className)) {

                if (element.className.length < 1) {

                    element.className = className;

                } else {

                    element.className += ' ' + className;

                }

            }

            return element;

        },

        removeClass: function (element, className) {

            /// <summary>

            ///     1: 为元素移除class

            ///     
    1.1 - addClass(element,className) - 为元素移除class,并返回修改后的class

            /// </summary>

            /// <param name="element" type="Element Or String">

            ///     节点对象

            /// </param>

            /// <param name="className" type="String">

            ///     Class Name

            /// </param>

            /// <returns type="Element" />

            if (tool.hasClass(element, className)) {

                var reg = new RegExp("(^|\\s)" + className + "(\\s|$)");

                element.className = element.className.replace(reg, '');

            }

            return element;

        },

        css: function (element, key) {

            /// <summary>

            ///     1: 获取元素css指定的属性值

            ///     
    1.1 - css(element,className) - 获取元素css指定的属性值

            /// </summary>

            /// <param name="element" type="Element Or String">

            ///     节点对象

            /// </param>

            /// <param name="key" type="String">

            ///     要获取的css属性

            /// </param>

            /// <returns type="String" />

            return element.currentStyle ? element.currentStyle[key] : document.defaultView.getComputedStyle(element, false)[key];

        },

        addEvent: function (element, type, fn) {

            /// <summary>

            ///     1: 为元素追加事件

            ///     
    1.1 - css(element, type, fn) - 为元素追加事件,函数中this指向事件源

            /// </summary>

            /// <param name="element" type="Element Or String">

            ///     节点对象

            /// </param>

            /// <param name="type" type="String">

            ///     追加的事件名,不含字符on

            /// </param>

            /// <param name="fn" type="Function">

            ///     事件对象

            /// </param>

            /// <returns type="void" />

            if (element.attachEvent) {

                element['e' + type + fn] = fn;

                element[type + fn] = function () { element['e' + type + fn](window.event); }

                element.attachEvent('on' + type, element[type + fn]);

            } else if (element.addEventListener) {

                element.addEventListener(type, fn, false);

            }

        },

        //        removeEvent: function (element, type, fn) {

        //            /// <summary>

        //            ///     1: 为元素删除事件,本函数并未用到

        //            ///     
    1.1 - removeEvent(element, type, fn) - 为元素删除事件

        //            /// </summary>

        //            /// <param name="element" type="Element Or String">

        //            ///     节点对象

        //            /// </param>

        //            /// <param name="type" type="String">

        //            ///     删除的事件名

        //            /// </param>

        //            /// <param name="key" type="String">

        //            ///     删除的事件的函数名

        //            /// </param>

        //            /// <returns type="void" />

        //            if (element.detachEvent) {

        //                element.detachEvent('on' + type, element[type + fn]);

        //                element[type + fn] = null;

        //            } else if (element.removeEventListener) {

        //                element.removeEventListener(type, fn, false);

        //            }

        //        },

        addScrollEvent: function (element, fn) {

            /// <summary>

            ///     1: 追加ScrollEvent事件

            ///     
    1.1 - addScrollEvent(element,fn) - 在元素上追加ScrollEvent事件(特殊事件,在元素上鼠标滚轮滚动事件)

            /// </summary>

            /// <param name="element" type="Element Or String">

            ///     元素节点

            /// </param>

            /// <param name="fn" type="Function">

            ///     事件方法

            /// </param>

            /// <returns type="void" />

            var bindScrollFn = function (e) {

                e = e || window.event;

                //判断滚轮滚动方向:Firefox和其他浏览器不同

                e.wheel = (e.wheelDelta ? e.wheelDelta : -e.detail) > 0 ? 1 : -1; // 通过事件判断鼠标滚轮反向,1是向上,-1是向下

                //阻止浏览器默认行为

                if (e.preventDefault) { //ff

                    e.preventDefault();

                } else {

                    e.returnValue = false; //ie

                }

                fn.call(element, e);

            }

            if (document.addEventListener) {

                //ff

                element.addEventListener('DOMMouseScroll', bindScrollFn, false);

                //w3c

                element.addEventListener('mousewheel', bindScrollFn, false);

            } else//ie

            {

                element.attachEvent('onmousewheel', bindScrollFn);

            }

        },

        getEvent: function () {

            /// <summary>

            ///     1: 获取Event对象 

            ///     
    1.1 - getEvent() - 在无参数的情况下获取Event对象,同时兼容性处理IE和FF

            /// </summary>

            /// <returns type="Event" />

            if (document.all) {

                return window.event;

            }

            func = getEvent.caller;

            while (func != null) {

                var arg0 = func.arguments[0];

                if (arg0) {

                    if ((arg0.constructor == Event || arg0.constructor == MouseEvent) || (typeof (arg0) == "object" && arg0.preventDefault && arg0.stopPropagation)) {

                        return arg0;

                    }

                }

                func = func.caller;

            }

            return null;

        },

        getMousePos: function (ev) {

            /// <summary>

            ///     1: 获取当前鼠标坐标 

            ///     
    1.1 - getMousePos(ev) - 获取当前鼠标坐标,兼容性处理,返回的对象格式:{ x:鼠标x坐标 , y:鼠标y坐标 }

            /// </summary>

            /// <param name="ev" type="Event">

            ///     Event事件对象

            /// </param>

            /// <returns type="Json" />

            if (!ev) {

                ev = currScroll.getEvent();

            }

            if (ev.pageX || ev.pageY) {

                return {

                    x: ev.pageX,

                    y: ev.pageY

                };

            }

            if (document.documentElement && document.documentElement.scrollTop) {

                return {

                    x: ev.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft,

                    y: ev.clientY + document.documentElement.scrollTop - document.documentElement.clientTop

                };

            }

            else if (document.body) {

                return {

                    x: ev.clientX + document.body.scrollLeft - document.body.clientLeft,

                    y: ev.clientY + document.body.scrollTop - document.body.clientTop

                };

            }

        },

        extend: function (oldObj, newObj) {

            /// <summary>

            ///     1: 将两个对象进行合并 

            ///     
    1.1 - extend(oldObj,newObj) - 将两个对象合并,并返回合并后的对象,采用clone的方式实现,所以不会对两个对象产生任何影响

            /// </summary>

            /// <param name="oldObj" type="Object">

            ///     要合并的对象A,该对象作为基础对象,将新对象的同名属性覆盖到基础对象中

            /// </param>

            /// <param name="newObj" type="Object">

            ///     要合并的对象B

            /// </param>

            /// <returns type="Object" />

            var tempObj = tool.clone(oldObj);

            for (var key in newObj) {

                if (newObj.hasOwnProperty(key) && !tempObj.hasOwnProperty(key)) {

                    tempObj[key] = newObj[key];

                }

            }

            return tempObj;

        },

        clone: function (obj) {

            /// <summary>

            ///     1: 克隆一个对象 

            ///     
    1.1 - clone(obj) - 克隆一个对象,并返回克隆后的新对象,该对象的原型是被克隆的对象

            /// </summary>

            /// <param name="obj" type="Object">

            ///     要克隆的对象

            /// </param>

            /// <returns type="Object" />

            function Clone() { }

            Clone.prototype = obj;

            var newObj = new Clone();

            for (var key in newObj) {

                if (typeof newObj[key] == "object") {

                    newObj[key] = tool.clone(newObj[key]);

                }

            }

            return newObj;

        },

        convertValue: function (value) {

            /// <summary>

            ///     1: 将数值转换为有效的数值

            ///     
    1.1 - convertValue(value) - 将Json配置的css数值转换为有效的数值,请保证value的值不为"auto"

            /// </summary>

            /// <param name="value" type="Object">

            ///     要转换的数值

            /// </param>

            /// <returns type="Object" />

            var reg = /^\d+$/g;

            if (typeof (value) === 'number' || reg.test(value)) {

                return value + 'px';

            } else

                return value;

        }

    };

    //注册到window下

    window.linkFlyScroll = linkFlyScroll;

    //注册到window.so命名空间下

    if (!window.so) {

        window.so = {};

    }

    window.so.scroll = window.linkFlyScroll;

})(window);

代码示例

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title></title>

    <link href="linkFlyScroll/linkFlyRollCss.css" rel="stylesheet" type="text/css" />

    <script src="linkFlyScroll/linkFlyScroll-1.0.0.js" type="text/javascript"></script>

    <script type="text/javascript">

        window.onload = function () {

            var config = {

                auto: true, //当内容并未达到容器的高度的时候,是否自动隐藏滚动条

                height: '100', //滚动条对象工作高度(超过该高度则显示滚动条),auto取对象当前高

                width: 'auto'//滚动条对象工作宽度

            };

            var scrollObj = so.scroll('obj', config);

            //            scrollObj.change();//当滚动条内容改变后,需要刷新滚动条的显示,则调用本方法

            //            scrollObj.roll(value);//把滚动条定位到某一点上,value为相对于滚动条对象的百分比

        };

    </script>

</head>

<body>

    <div id="obj">

        <div>

            当前,企业管理领域刮起一股新的“时尚风”,一些巨头企业纷纷为自己“瘦身”,向更智慧和灵动的业务转型。据了解,甲骨文软件正越来越多地把客户的主要维护成本向咨询顾问和第三方供应商转移。

            “在中国本土,90%的甲骨文公司业务是通过这些合作伙伴开展的。此外,为了进一步确保甲骨文的收入,CEO埃里森还购买了夏威夷的一个小岛。” Craig Guarente说道。

            作为全球副总裁,Guarente非常清楚甲骨文的各项战略。Guarente具有16年的工作经历,曾在合同管理、软件许可证管理、软件审计方面有丰富经验。2011年离开甲骨文后,加入了Palisade公司,该公司的主要业务是帮助甲骨文客户提供软件承包、审计介入和许可证“优化”等业务。

            Guarente表示,Palisade公司业务发展非常迅速。作为第三方机构,Palisade帮助客户赢得了大笔订单,因为他们更贴近市场,能更准确地理解用户需求。

            一般来说,咨询公司是帮助客户梳理他的实际需求及软件本身能提供什么价值。Guarente通过实际操作做了详细阐述。比如“你想建设一个新的数据中心,想要推出一个新的灾难恢复计划,或者你想进入云端,第三方公司首先会制定一个规划图,最后落实,达成用户最终目标。如果把软件部署在很多服务器的不同位置上,企业会有丢失软件的现象。因为企业软件很少能得到许可证密钥。但Oracle已经形成习惯,每一个可能功能都可以在软件环境下下载。Oracle数据库管理员通过自动负载的存储库(AWR)报告就可以诊断数据库问题,这是常见的事,但需要你有一个Oracle数据库包的许可。”

            近年来,随着软件审计浪潮的兴起,许多公司正在安装软件资产管理工具来确定他们使用什么软件,能使用多长时间,一个企业多少人在用。但资深管理分析师Hegedus说到:“没有任何工具能准确理解企业规则,尤其是甲骨文的产品应用,需要专业的第三方机构来帮助用户理解软件规则。”

            那么怎么才能为甲骨文的软件应用打补丁呢?甲骨文总裁马克•赫德(Mark Hurd)上周表示:在企业应用之初要把第三方机构定义为服务支持方,这样方便企业日后免费获得补丁修复和其他支持,而不只是购买产品知识产权。另外,企业要有效利用咨询顾问,在了解企业使用什么软件,协议应该包含什么内容时,支持成本控制的第一步。不要盲目离开软件供应商,按照自己预测和猜想的流程采购软件。

        </div>

    </div>

</body>

</html>

以上就是本文的全部内容了,讲解的十分详细,希望大家能够喜欢。

Javascript 相关文章推荐
用JQuery 实现的自定义对话框
Mar 24 Javascript
javascript 解析url的search方法
Feb 09 Javascript
js限制文本框为整数和货币的函数代码
Oct 13 Javascript
js树插件zTree获取所有选中节点数据的方法
Jan 28 Javascript
jQuery判断浏览器并动态调整select宽度的方法
Mar 02 Javascript
JavaScript学习笔记之数组随机排序
Mar 23 Javascript
JS实现兼容各种浏览器的高级拖动方法完整实例【测试可用】
Jun 21 Javascript
利用Angularjs和原生JS分别实现动态效果的输入框
Sep 01 Javascript
javascript函数的节流[throttle]与防抖[debounce]
Nov 15 Javascript
vue项目打包后打开页面空白解决办法
Jun 29 Javascript
解决Vue+Element ui开发中碰到的IE问题
Sep 03 Javascript
jquery插件开发模式实例详解
Jul 20 jQuery
深入理解JavaScript系列(35):设计模式之迭代器模式详解
Mar 03 #Javascript
jQuery选择器之基本选择器与层次选择器
Mar 03 #Javascript
JS实现在网页中弹出一个输入框的方法
Mar 03 #Javascript
深入理解JavaScript系列(34):设计模式之命令模式详解
Mar 03 #Javascript
深入理解JavaScript系列(33):设计模式之策略模式详解
Mar 03 #Javascript
JavaScript模拟重力状态下抛物运动的方法
Mar 03 #Javascript
深入理解JavaScript系列(31):设计模式之代理模式详解
Mar 03 #Javascript
You might like
cache_lite试用
2007/02/14 PHP
PHP使用GIFEncoder类生成的GIF动态图片验证码
2014/07/01 PHP
php约瑟夫问题解决关于处死犯人的算法
2015/03/23 PHP
PHP图片加水印实现方法
2016/05/06 PHP
PHPMailer使用QQ邮箱实现邮件发送功能
2017/08/18 PHP
PHP缓存工具XCache安装与使用方法详解
2018/04/09 PHP
非常好用的JsonToString 方法 简单实例
2013/07/18 Javascript
深入理解JQuery keyUp和keyDown的区别
2013/12/12 Javascript
javascript 终止函数执行操作
2014/02/14 Javascript
javascript实现可拖动变色并关闭层窗口实例
2015/05/15 Javascript
实例详解angularjs和ajax的结合使用
2015/10/22 Javascript
bootstrap datepicker限定可选时间范围实现方法
2016/09/28 Javascript
js 提交form表单和设置form表单请求路径的实现方法
2016/10/25 Javascript
JSON中key动态设置及JSON.parse和JSON.stringify()的区别
2016/12/29 Javascript
Easyui笔记2:实现datagrid多行删除的示例代码
2017/01/14 Javascript
最常见和最有用的字符串相关的方法详解
2017/02/06 Javascript
JS实现最简单的冒泡排序算法
2017/02/15 Javascript
JS ES6中setTimeout函数的执行上下文示例
2017/04/27 Javascript
解决vue2中使用axios http请求出现的问题
2018/03/05 Javascript
webpack+vue+express(hot)热启动调试简单配置方法
2018/09/19 Javascript
layer弹出层扩展主题的方法
2019/09/11 Javascript
javascript 关于赋值、浅拷贝、深拷贝的个人理解
2019/11/01 Javascript
vue分页插件的使用方法
2019/12/25 Javascript
[02:19]2018年度DOTA2最佳核心位选手-完美盛典
2018/12/17 DOTA
Python语言技巧之三元运算符使用介绍
2013/03/04 Python
设计模式中的原型模式在Python程序中的应用示例
2016/03/02 Python
Python 正则表达式入门(中级篇)
2016/12/07 Python
python实现聊天小程序
2018/03/13 Python
Python实现在某个数组中查找一个值的算法示例
2018/06/27 Python
NLTK 3.2.4 环境搭建教程
2018/09/19 Python
python3 re返回形式总结
2020/11/20 Python
垃圾回收的优点和原理。并考虑2种回收机制
2016/10/16 面试题
公司联欢会策划方案
2014/05/19 职场文书
2015年信息技术教研组工作总结
2015/07/22 职场文书
求职信:求职应该注意的问题
2019/04/24 职场文书
JavaScript实现一键复制内容剪贴板
2022/07/23 Javascript