找回密码
 注册账户
查看: 1999|回复: 1

AJAX Bookmarking System, JavaScript Menu

[复制链接]
棋子 发表于 2007-7-22 15:16:34 | 显示全部楼层 |阅读模式
演示地址
http://www.vibe.to/js/stew/ajaxmenu.php

代码
Yesterday I was immersed in code throughout the day. I was on the task of creating an AJAX bookmarking system (I freaking love AJAX by the way.) There are four parts to the current system:

    * Adding Bookmarks
    * Viewing Quick Bookmarks
    * Viewing All Bookmarks
    * Deleting Bookmarks

Soon to be added:

    * Tag Bookmarks
    * Arrange Bookmarks

Languages/Tools Used
PHP, DOM, AJAX, JavaScript, MySQL

The Table (MySQL)

CREATE TABLE `favs` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `userid` int(10) unsigned NOT NULL default '0',
  `url` varchar(100) NOT NULL default '',
  `title` varchar(100) NOT NULL default '',
  `favtime` timestamp NOT NULL default CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`),
  KEY `userid` (`userid`)
)

If you’re curious, I called the table favs because of poor planning, no other reason. bookmarks would be preferred.

Adding Bookmarks
A very easy step. The button sends the document title and document url through AJAX to a php file that will save the row in the database.

var isActive;
var timeout;

function add2Fav(userid)
{
        if (!userid)
        {
                alert("You must login before you can bookmark pages");
                return
        }
        xmlHttp = GetXmlHttpObject();

        var docURL = document.location;
        var docTitle = document.title;

        var url = "_ajax.add2Fav.php";
        url = url + "?userid=" + userid;
        url = url + "&url=" + escape(docURL);
        url = url + "&title=" + escape(docTitle);
        url = url + "&rand=" + Math.random();

        xmlHttp.onreadystatechange=doOutput;
        xmlHttp.open("GET",url,true);
        xmlHttp.send(null);

        function doOutput()
        {
                if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete")
                {
                        isActive = null; // deactivate the bookmark menu

                        if (xmlHttp.responseText == "1")
                        {
                                alert("You have successfully bookmarked this page.nn" + docTitle);
                        }
                        else
                        {
                                alert("We couldn't save the page to your favourites list because of an error");
                        }
                }
        }
}

Fairly straightforward. Users must be logged in to save bookmarks, I was thinking about implementing cookies, but that would just make things much more confusing. If they’re not logged in we just prompt them to log in. The PHP file returns “1″ (string) if the row is saved.

AJAX=>PHP: Add Bookmark

<~?
        # db connection

        $user_id = intval($_GET['userid']);
        if ($user_id == 0) exit("0"); // invalid userID!

        mysql_query("INSERT INTO favs (userid, url, title) VALUES ('{$user_id}', '".mysql_escape_string($_GET['url'])."', '".mysql_escape_string($_GET['title'])."')");
        if (mysql_affected_rows() > 0) echo “1″;
        else echo mysql_error();
?~>

Quick Bookmarks
This is the cream of the crop. I needed a way to implement the bookmarking system on the site that was unobtrusive, but would still be easy enough to load up that they would be useful. My solution was to offer a drop down menu right next to the “Add Bookmark” button. The menu has to load up relative to the button, so I had to find its coordinates using clientX and clientY, as well as offsetLeft, OffsetTop and offsetParent. Because Internet Explorer and FireFox read these different I had to use quirksmode findPos function to bridge the browser differences. Then, after I had it working, I decided a snazzy fade effect would look brilliant, so I coded a fadeIn() and fadeOut() function to play with the CSS alpha.

function showBookmarks(e, userid)
{
        var divid = 'favmenu';
        var heightPX = 27; // define the elements height in PX
        var widthPX = -301;

        if (!isActive) // make sure they've only clicked the link once
        {
                isActive = 1; // the menu is active

                e = e ? e : window.event; // ff : ie
                var obj = e.target ? e.target : e.srcElement; // ff : ie

                xmlHttp = GetXmlHttpObject();
                xmlHttp.onreadystatechange = doBookmarksAJAX;
                xmlHttp.open("GET","_ajax.getBookmarks.php?userid="+userid+"&rand="+Math.random(),true);
                xmlHttp.send(null);
        }

        function doBookmarksAJAX()
        {
                if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete")
                {
                        var parent = document.getElementById('topRightDiv');
                        var absOffset = findPos(parent);
                        var menu = document.createElement('div');
                        menu.setAttribute('id', divid);
                        //menu.className = 'favMenu';

                        var leftPX = parseInt(absOffset[0]) + widthPX;
                        menu.style.left =  leftPX + 'px';

                        var topPX = parseInt(absOffset[1]) + heightPX; // top of object + object size
                        menu.style.top = topPX + 'px'

                        parent.appendChild(menu)
                        document.getElementById(divid).innerHTML = xmlHttp.responseText;

                        fadeIn(0, divid);

                        menu.onmouseout = function()
                        {
                                timeout = window.setTimeout("hideBookmarks(1)", 3000);
                        }
                        menu.onmouseover = function()
                        {
                                if (timeout)
                                {
                                        clearTimeout(timeout);
                                } // else they haven't put their mouse over the menu yet
                        }       

                }
        } // end
}

function hideBookmarks(fade)
{
        var ms = fade ? 350 : 1; // 350 = fade delay, 1 = instant
        if (!fade)
        {
                if (timeout)
                {
                        clearTimeout(timeout);
                }
                isActive = 0;
                var menu = document.getElementById('favmenu');
                var parent = document.getElementById('topRightDiv');
                parent.removeChild(menu);
        }
        else
        {
                fadeOut(100, 'favmenu');
                setTimeout("hideBookmarks(0)", ms);
        }
}

function findPos(obj)
{
        var curleft = curtop = 0;
        if (obj.offsetParent) {
                curleft = obj.offsetLeft
                curtop = obj.offsetTop
                while (obj = obj.offsetParent) {
                        curleft += obj.offsetLeft
                        curtop += obj.offsetTop
                }
        }
        return [curleft,curtop];
}

function fadeIn(opacity, objname)
{
        obj = document.getElementById(objname);
        if (obj)
        {
                if (opacity <= 100)
                {
                        if (obj.style.MozOpacity != null)
                        {
                                /* Mozilla's pre-CSS3 proprietary rule */
                                obj.style.MozOpacity = (opacity/100)-.001;
                                /* the .001 fixes a glitch in the opacity calculation which normally results in a flash when reaching 1 */
                        } else if (obj.style.opacity != null)
                        {
                                /* CSS3 compatible */
                                obj.style.opacity = (opacity/100)-.001;
                        } else if (obj.style.filter != null)
                        {
                                /* IE's proprietary filter */
                                obj.style.filter = "alpha(opacity="+opacity+")";
                                /* worth noting: IE's opacity needs values in a range of 0-100, not 0.0 - 1.0 */
                        }
                        opacity += 10;
                        window.setTimeout("fadeIn("+opacity+", '"+objname+"')", 35);
                }
        }
}

function fadeOut(opacity, objname)
{
        obj = document.getElementById(objname);
        if (obj)
        {
                if (opacity >= 0)
                {
                        if (obj.style.MozOpacity != null)
                        {
                                /* Mozilla’s pre-CSS3 proprietary rule */
                                obj.style.MozOpacity = (opacity/100)-.001;
                                /* the .001 fixes a glitch in the opacity calculation which normally results in a flash when reaching 1 */
                        } else if (obj.style.opacity != null)
                        {
                                /* CSS3 compatible */
                                obj.style.opacity = (opacity/100)-.001;
                        } else if (obj.style.filter != null)
                        {
                                /* IE’s proprietary filter */
                                obj.style.filter = “alpha(opacity=”+opacity+”)”;
                                /* worth noting: IE’s opacity needs values in a range of 0-100, not 0.0 - 1.0 */
                        }
                        opacity -= 10;
                        window.setTimeout(”fadeOut(”+opacity+”, ‘”+objname+”‘)”, 35);
                }
        }
}

Call to action: onClick=”showBookmarks(event, ‘{$userID}’);”
event = passes the event information to the function (same as window.event)
$userID = userID from $_SESSION

Viewing/deleting the full bookmark list is a standard page, but to keep the AJAX trend I made it delete in real time via AJAX. Last block of code, I swear!

function deleteBookmark(obj, userid, id)
{
        var row = obj.parentNode.parentNode; // two steps up
        if (row.nodeName.toUpperCase() == 'TR')
        {
                row.parentNode.removeChild(row);
                ajaxStatus('Deleting bookmark...');
                xmlHttp = GetXmlHttpObject();
                xmlHttp.onreadystatechange=doDelete;
                xmlHttp.open("GET","http://www.vibe.to/_ajax.deleteBookmark.php?userid="+userid+"&id="+id,true);
                xmlHttp.send(null);
        }

        function doDelete()
        {
                if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete")
                {
                        if (xmlHttp.responseText == "1")
                        {
                                // done... don't need to do anything
                        } else alert(xmlHttp.responseText);

                        ajaxStatus();
                }
        }
}

Call to action: onClick=”javascript:deleteBookmark(this, ‘{$userID}’, ‘{$bookmarkID}’);”
this = references the link or button that is clicked
$userID = is the users unique number (from $_SESSION)
$bookmarkID = the bookmark row (from the query result)

I implemented this system on my social networking site so users can bookmark their favourite forum threads, people and, well, basically any page. Example of quick view available here
asdfasdf 发表于 2008-10-4 08:00:09 | 显示全部楼层
ע:ż
您需要登录后才可以回帖 登录 | 注册账户

本版积分规则

存档|黑屋|手机|网络实验室 本站服务器由美国合租以及IDCLayer国际数据提供!!!

GMT+8, 2026-6-9 09:58 , Processed in 0.010760 second(s), 8 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表