[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

abarth at webkit.org abarth at webkit.org
Wed Dec 22 13:25:50 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit f4051f31f393672706e0274f85f056e7fc1c96ab
Author: abarth at webkit.org <abarth at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Sep 15 02:04:55 2010 +0000

    2010-09-14  Adam Barth  <abarth at webkit.org>
    
            Reviewed by Eric Seidel.
    
            bugs.webkit.org should autocomplete WebKit Committers and Reviewers
            https://bugs.webkit.org/show_bug.cgi?id=45799
    
            This patch implements an autocomplete dropdown that helps users type
            the names of WebKit committers and reviewers.  The script grabs the
            data from SVN now that wms set up CORS for http://svn.webkit.org.
            Security technology for the win.
    
            This script is based on (well, essentially copied from) the popular
            autocomplete extension:
    
            https://chrome.google.com/extensions/detail/olaabhcgdogcbcoiolomlcodkngnemfb
    
            I asked Ojan, and said he was fine licensing the code under the BSD
            license.  I'm not sure how the patch interacts with the extension, but
            we can retire the extension if they interact poorly.
    
            * committers-autocomplete.js: Added.
            * template/en/default/global/footer.html.tmpl:
                - Add the script to every page on bugs.webkit.org
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@67528 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/BugsSite/ChangeLog b/BugsSite/ChangeLog
index 211c8c6..14457d2 100644
--- a/BugsSite/ChangeLog
+++ b/BugsSite/ChangeLog
@@ -1,5 +1,30 @@
 2010-09-14  Adam Barth  <abarth at webkit.org>
 
+        Reviewed by Eric Seidel.
+
+        bugs.webkit.org should autocomplete WebKit Committers and Reviewers
+        https://bugs.webkit.org/show_bug.cgi?id=45799
+
+        This patch implements an autocomplete dropdown that helps users type
+        the names of WebKit committers and reviewers.  The script grabs the
+        data from SVN now that wms set up CORS for http://svn.webkit.org.
+        Security technology for the win.
+
+        This script is based on (well, essentially copied from) the popular
+        autocomplete extension:
+
+        https://chrome.google.com/extensions/detail/olaabhcgdogcbcoiolomlcodkngnemfb
+
+        I asked Ojan, and said he was fine licensing the code under the BSD
+        license.  I'm not sure how the patch interacts with the extension, but
+        we can retire the extension if they interact poorly.
+
+        * committers-autocomplete.js: Added.
+        * template/en/default/global/footer.html.tmpl:
+            - Add the script to every page on bugs.webkit.org
+
+2010-09-14  Adam Barth  <abarth at webkit.org>
+
         Add a license block to the reviewtool.  I should have added this from
         the start.  According to the SVN log, I'm the only one to have ever
         touched this file.
diff --git a/BugsSite/committers-autocomplete.js b/BugsSite/committers-autocomplete.js
new file mode 100644
index 0000000..b2e20fd
--- /dev/null
+++ b/BugsSite/committers-autocomplete.js
@@ -0,0 +1,387 @@
+// Copyright (C) 2010 Ojan Vafai. All rights reserved.
+// Copyright (C) 2010 Adam Barth. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+
+WebKitCommitters = (function() {
+    var COMMITTERS_URL = 'http://svn.webkit.org/repository/webkit/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py';
+    var m_committers;
+
+    function getValues(param) {
+        var nextQuote = /^[^"]*"/g;
+        var values = [];
+        nextQuote.lastIndex = 0;
+        while (nextQuote.exec(param) != null) {
+            var nextIndex = param.indexOf('"', nextQuote.lastIndex); // For emacs " to balance the quotes.
+            values.push(param.substring(nextQuote.lastIndex, nextIndex));
+            param = param.substring(nextIndex + 1);
+            nextQuote.lastIndex = 0;
+        }
+        return values;
+    }
+
+    function parseRecord(key, record) {
+        var keyIndex = record.indexOf(key);
+        if (keyIndex < 0)
+            return null;
+        record = record.substring(keyIndex + key.length);
+
+        var firstParen = /^\s*\(\s*/g;
+        firstParen.lastIndex = 0;
+        if (!firstParen.exec(record))
+            return null;
+        record = record.substring(firstParen.lastIndex);
+
+        var parsedResult = {};
+
+        // full name
+        var param = /^\s*((\[[^\]]+\])|("[^"]+"))\s*/g; // For emacs " to balance the quotes.
+        param.lastIndex = 0;
+        var nameParam = param.exec(record);
+        if (!nameParam)
+            return null;
+        record = record.substring(param.lastIndex);
+
+        // Save the name without the quotes.
+        parsedResult.name = nameParam[0].slice(1, nameParam[0].length - 1);
+
+        var paramSeparator = /^\s*,\s*/g;
+        paramSeparator.lastIndex = 0;
+        if (!paramSeparator.exec(record))
+            return null;
+        record = record.substring(paramSeparator.lastIndex);
+
+        // email
+        param.lastIndex = 0;
+        emailParam = param.exec(record);
+        if (!emailParam)
+            return null;
+
+        emails = getValues(emailParam[0]);
+        parsedResult.emails = emails;
+        record = record.substring(param.lastIndex);
+
+        paramSeparator.lastIndex = 0;
+        if (!paramSeparator.exec(record))
+            return parsedResult;
+        record = record.substring(paramSeparator.lastIndex);
+
+        // irc
+        param.lastIndex = 0;
+        ircParam = param.exec(record);
+        if (!ircParam)
+            return parsedResult;
+        record = record.substring(param.lastIndex);
+
+        irc = getValues(ircParam[0]);
+        parsedResult.irc = irc;
+        return parsedResult;
+    }
+
+    function parseType(key, records, type) {
+        for (var i = 0; i < records.length; ++i) {
+            var record = records[i];
+            var result = parseRecord(key, record);
+            if (!result)
+                continue;
+            result.type = type;
+            m_committers.push(result);
+        }
+    }
+
+    function parseCommittersPy(text) {
+        m_committers = [];
+
+        var records = text.split('\n');
+        parseType('Committer', records, 'c');
+        parseType('Reviewer', records, 'r');
+    }
+
+    function loadCommitters(callback) {
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', COMMITTERS_URL);
+
+        xhr.onload = function() {
+            parseCommittersPy(xhr.responseText);
+            callback();
+        };
+
+        xhr.onerror = function() {
+            console.log('Unable to load committers.py');
+            callback();
+        };
+
+        xhr.send();
+    }
+
+    function getCommitters(callback) {
+        if (m_committers) {
+            callback(m_committers);
+            return;
+        }
+
+        loadCommitters(function() {
+            callback(m_committers);
+        });
+    }
+
+    return {
+        "getCommitters": getCommitters
+    };
+})();
+
+(function() {
+    var SINGLE_EMAIL_INPUTS = ['email1', 'email2', 'requester', 'requestee', 'assigned_to'];
+    var EMAIL_INPUTS = SINGLE_EMAIL_INPUTS.concat(['cc', 'newcc', 'new_watchedusers']);
+
+    var m_menus = {};
+    var m_focusedInput;
+    var m_committers;
+    var m_prefix;
+    var m_selectedIndex;
+
+    function contactsMatching(prefix) {
+        var list = [];
+        if (!prefix)
+            return list;
+
+        for (var i = 0; i < m_committers.length; i++) {
+            if (isMatch(m_committers[i], prefix))
+                list.push(m_committers[i]);
+        }
+        return list;
+    }
+
+    function startsWith(str, prefix) {
+        return str.toLowerCase().indexOf(prefix.toLowerCase()) == 0;
+    }
+
+    function startsWithAny(arry, prefix) {
+        for (var i = 0; i < arry.length; i++) {
+            if (startsWith(arry[i], prefix))
+                return true;
+        }
+        return false;
+    }
+
+    function isMatch(contact, prefix) {
+        if (startsWithAny(contact.emails, prefix))
+            return true;
+
+        if (contact.irc && startsWithAny(contact.irc, prefix))
+            return true;
+
+        var names = contact.name.split(' ');
+        for (var i = 0; i < names.length; i++) {
+            if (startsWith(names[i], prefix))
+                return true;
+        }
+        
+        return false;
+    }
+
+    function isMenuVisible() {
+        return getMenu().style.display != 'none';
+    }
+
+    function showMenu(shouldShow) {
+        getMenu().style.display = shouldShow ? '' : 'none';
+    }
+
+    function updateMenu() {
+        var newPrefix = m_focusedInput.value;
+        if (newPrefix) {
+            newPrefix = newPrefix.slice(getStart(), getEnd());
+            newPrefix = newPrefix.replace(/^\s+/, '');
+            newPrefix = newPrefix.replace(/\s+$/, '');
+        }
+
+        if (m_prefix == newPrefix)
+            return;
+
+        m_prefix = newPrefix;
+
+        var contacts = contactsMatching(m_prefix);
+        if (contacts.length == 0 || contacts.length == 1 && contacts[0].emails[0] == m_prefix) {
+            showMenu(false);
+            return;
+        }
+
+        var html = [];
+        for (var i = 0; i < contacts.length; i++) {
+            var contact = contacts[i];
+            html.push('<div style="padding:1px 2px;" ' + 'email=' +
+                contact.emails[0] + '>' + contact.name + ' - ' + contact.emails[0]);
+            if (contact.irc)
+                html.push(' (:' + contact.irc + ')');
+            html.push(' (' + contact.type + ')');
+            html.push('</div>');
+        }
+        getMenu().innerHTML = html.join('');
+        selectItem(0);
+        showMenu(true);
+    }
+
+    function getIndex(item) {
+        for (var i = 0; i < getMenu().childNodes.length; i++) {
+            if (item == getMenu().childNodes[i])
+                return i;
+        }
+        console.error("Couldn't find item.");
+    }
+
+    function getMenu() {
+        return m_menus[m_focusedInput.name];
+    }
+
+    function createMenu(name, input) {
+        if (!m_menus[name]) {
+            var menu = document.createElement('div');
+            menu.style.cssText =
+                "position:absolute;border:1px solid black;background-color:white;-webkit-box-shadow:3px 3px 3px #888;";
+            menu.style.minWidth = m_focusedInput.offsetWidth + 'px';
+            m_focusedInput.parentNode.insertBefore(menu, m_focusedInput.nextSibling);
+
+            menu.addEventListener('mousedown', function(e) {
+                selectItem(getIndex(e.target));
+                e.preventDefault();
+            });
+
+            menu.addEventListener('mouseup', function(e) {
+                if (m_selectedIndex == getIndex(e.target))
+                    insertSelectedItem();
+            });
+            
+            m_menus[name] = menu;
+        }
+    }
+
+    function getStart() {
+        var index = m_focusedInput.value.lastIndexOf(',', m_focusedInput.selectionStart - 1);
+        if (index == -1)
+            return 0;
+        return index + 1;
+    }
+
+    function getEnd() {
+        var index = m_focusedInput.value.indexOf(',', m_focusedInput.selectionStart);
+        if (index == -1)
+            return m_focusedInput.value.length;
+        return index;
+    }
+
+    function getItem(index) {
+        return getMenu().childNodes[index];
+    }
+
+    function selectItem(index) {
+        if (index < 0 || index >= getMenu().childNodes.length)
+            return;
+
+        if (m_selectedIndex != undefined) {
+            getItem(m_selectedIndex).style.backgroundColor = '';
+            getItem(m_selectedIndex).style.color = '';
+        }
+
+        getItem(index).style.backgroundColor = '#039';
+        getItem(index).style.color = 'white';
+
+        m_selectedIndex = index;
+    }
+
+    function insertSelectedItem() {
+        var selectedEmail = getItem(m_selectedIndex).getAttribute('email');
+        var oldValue = m_focusedInput.value;
+
+        var newValue = oldValue.slice(0, getStart()) + selectedEmail + oldValue.slice(getEnd());
+        if (SINGLE_EMAIL_INPUTS.indexOf(m_focusedInput.name) == -1 &&
+            newValue.charAt(newValue.length - 1) != ',')
+            newValue = newValue + ',';
+
+        m_focusedInput.value = newValue;
+        showMenu(false);    
+    }
+
+    function handleKeyDown(e) {
+        if (!isMenuVisible())
+            return;
+
+        switch (e.keyIdentifier) {
+            case 'Up':
+                selectItem(m_selectedIndex - 1);
+                e.preventDefault();
+                break;
+            
+            case 'Down':
+                selectItem(m_selectedIndex + 1);
+                e.preventDefault();
+                break;
+                
+            case 'Enter':
+                insertSelectedItem();
+                e.preventDefault();
+                break;
+        }
+    }
+
+    function handleKeyUp(e) {
+        if (e.keyIdentifier == 'Enter')
+            return;
+
+        if (m_focusedInput.selectionStart == m_focusedInput.selectionEnd)
+            updateMenu();
+        else
+            showMenu(false);
+    }
+
+    function enableAutoComplete(input) {
+        m_focusedInput = input;
+
+        if (!getMenu()) {
+            createMenu(m_focusedInput.name);
+            m_focusedInput.setAttribute('autocomplete', 'off');
+            m_focusedInput.addEventListener('keyup', handleKeyUp);
+            m_focusedInput.addEventListener('keydown', handleKeyDown);
+            m_focusedInput.addEventListener('blur', function() {
+                showMenu(false);
+                m_prefix = null;
+                m_selectedIndex = 0;
+            });
+        }
+        
+        updateMenu();
+    }
+
+    document.addEventListener('focusin', function(e) {
+        for (var i = 0; i < EMAIL_INPUTS.length; i++) {
+            if (e.target.name == EMAIL_INPUTS[i]) {
+                enableAutoComplete(e.target);
+                break;
+            }
+        }
+    });
+
+    WebKitCommitters.getCommitters(function (committers) {
+        m_committers = committers;
+    });
+})();
diff --git a/BugsSite/template/en/default/global/footer.html.tmpl b/BugsSite/template/en/default/global/footer.html.tmpl
index 0379f02..205c978 100644
--- a/BugsSite/template/en/default/global/footer.html.tmpl
+++ b/BugsSite/template/en/default/global/footer.html.tmpl
@@ -43,7 +43,7 @@
 
   <div class="outro"></div>
 </div>
-
+<script defer src="/committers-autocomplete.js"></script>
 </body>
 </html>
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list