mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-11-25 04:06 am

[dw-free] set up RTE to use the cross-site tags

[commit: http://hg.dwscoalition.org/dw-free/rev/13b9b8990773]

http://bugs.dwscoalition.org/show_bug.cgi?id=496

Allow RTE to support external site tags.

Patch by [personal profile] afuna.

Files modified:
  • bin/upgrading/en.dat
  • cgi-bin/weblib.pl
  • htdocs/js/rte.js
  • htdocs/stc/entry.css
  • htdocs/stc/fck/editor/plugins/livejournal/fckplugin.js
  • htdocs/tools/endpoints/ljuser.bml
--------------------------------------------------------------------------------
diff -r 0e9424044833 -r 13b9b8990773 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat	Wed Nov 25 03:56:46 2009 +0000
+++ b/bin/upgrading/en.dat	Wed Nov 25 04:06:39 2009 +0000
@@ -2031,6 +2031,10 @@ fcklang.readmore=Read more...
 
 fcklang.userprompt=Enter their username
 
+fcklang.userprompt.site=External Site (optional)
+
+fcklang.userprompt.user=Username
+
 fcklang.videoprompt=Please enter the YouTube, PhotoBucket, or Google Video URL:
 
 feeds.link=syndicated feeds
diff -r 0e9424044833 -r 13b9b8990773 cgi-bin/weblib.pl
--- a/cgi-bin/weblib.pl	Wed Nov 25 03:56:46 2009 +0000
+++ b/cgi-bin/weblib.pl	Wed Nov 25 04:06:39 2009 +0000
@@ -10,6 +10,7 @@ require "crumbs.pl";
 require "crumbs.pl";
 
 use Carp;
+use DW::External::Site;
 use DW::Request;
 use LJ::Event;
 use LJ::Subscription::Pending;
@@ -1407,9 +1408,18 @@ sub entry_form {
         if (t) {
 RTE
 
+    my @sites = DW::External::Site->get_sites;
+    my @sitevalues;
+    foreach my $site (sort { $a->{sitename} cmp $b->{sitename} } @sites) {
+        push @sitevalues, { domain => $site->{domain}, sitename => $site->{sitename} };
+    }
+
     $out .= "var FCKLang;\n";
     $out .= "if (!FCKLang) FCKLang = {};\n";
     $out .= "FCKLang.UserPrompt = \"".LJ::ejs(BML::ml('fcklang.userprompt'))."\";\n";
+    $out .= "FCKLang.UserPrompt_User = \"".LJ::ejs(BML::ml('fcklang.userprompt.user'))."\";\n";
+    $out .= "FCKLang.UserPrompt_Site = \"".LJ::ejs(BML::ml('fcklang.userprompt.site'))."\";\n";
+    $out .= "FCKLang.UserPrompt_SiteList =" . LJ::js_dumper( \@sitevalues ) . ";\n";
     $out .= "FCKLang.InvalidChars = \"".LJ::ejs(BML::ml('fcklang.invalidchars'))."\";\n";
     $out .= "FCKLang.LJUser = \"".LJ::ejs(BML::ml('fcklang.ljuser'))."\";\n";
     $out .= "FCKLang.VideoPrompt = \"".LJ::ejs(BML::ml('fcklang.videoprompt'))."\";\n";
diff -r 0e9424044833 -r 13b9b8990773 htdocs/js/rte.js
--- a/htdocs/js/rte.js	Wed Nov 25 03:56:46 2009 +0000
+++ b/htdocs/js/rte.js	Wed Nov 25 04:06:39 2009 +0000
@@ -8,15 +8,22 @@ function LJUser(textArea) {
 
     var html = oEditor.GetXHTML(false);
     if (html) html = html.replace(/<\/(lj|user)>/, '');
-    var regexp = /<(?:lj user|user name)=['"](\w+?)['"] ?\/?>\s?(?:<\/(?:lj|user)>)?\s?/g;
+    var regexp = /<(?:lj|user)( (?:user|name|site)=[^/>]+)\/?>\s?(?:<\/(?:lj|user)>)?\s?/g;
+    var attrs_regexp = /(user|name|site)=['"]([.\w]+?)['"]/g;
     var userstr;
     var users = [];
     var username;
+
     while ((users = regexp.exec(html))) {
-        username = users[1];
-        var postData = {
-            "username" : username
-        };
+        var attrs = [];
+        var postData = {};
+
+        while (( attrs=attrs_regexp.exec(users[1]) )) {
+            if (attrs[1] == 'user' || attrs[1] == 'name')
+                postData.username = attrs[2];
+            else 
+                postData[attrs[1]] = attrs[2];
+        }
         var url = window.parent.Site.siteroot + "/tools/endpoints/ljuser";
 
         var gotError = function(err) {
@@ -24,18 +31,27 @@ function LJUser(textArea) {
             return;
         }
 
-        var gotInfo = function (data) {
+        var gotInfo = (function (userstr, username, site) { return function(data) {
+            // trim any trailing spaces from the userstr
+            // so that we don't get rid of them when we do the replace below
+            userstr = userstr.replace(/\s\s*$/, '');
+
             if (data.error) {
                 alert(data.error+' '+username);
                 return;
             }
             if (!data.success) return;
-            data.ljuser = data.ljuser.replace(/<span.+?class=['"]?ljuser['"]?.+?>/,'<div class="ljuser">');
+
+            if ( site ) 
+                data.ljuser = data.ljuser.replace(/<span.+?class=['"]?ljuser['"]?.+?>/,'<div class="ljuser" site="' + site + '">');
+            else 
+                data.ljuser = data.ljuser.replace(/<span.+?class=['"]?ljuser['"]?.+?>/,'<div class="ljuser">');
+
             data.ljuser = data.ljuser.replace(/<\/span>\s?/,'</div>');
-            html = html.replace(data.userstr,data.ljuser);
+            html = html.replace(userstr,data.ljuser);
             oEditor.SetData(html);
             oEditor.Focus();
-        }
+        }})(users[0], postData.username, postData.site);
 
         var opts = {
             "data": window.parent.HTTPReq.formEncoded(postData),
@@ -245,7 +261,10 @@ function doLinkedFieldUpdate(oEditor) {
 }
 
 function convertToTags(html) {
+    // no site
     html = html.replace(/<div class=['"]ljuser['"]>.+?<b>(\w+?)<\/b><\/a><\/div>/g, '<user name=\"$1\">');
+    // with site
+    html = html.replace(/<div(?: site=['"](.+?)['"]) class=['"]ljuser['"]>.+?<b>(\w+?)<\/b><\/a><\/div>/g, '<user name=\"$2\" site=\"$1\">');
     html = html.replace(/<div class=['"]ljvideo['"] url=['"](\S+)['"]><img.+?\/><\/div>/g, '<site-template name=\"video\">$1</site-template>');
     html = html.replace(/<div class=['"]ljvideo['"] url=['"](\S+)['"]><br \/><\/div>/g, '');
     html = html.replace(/<div class=['"]ljraw['"]>(.+?)<\/div>/g, '<raw-code>$1</raw-code>');
diff -r 0e9424044833 -r 13b9b8990773 htdocs/stc/entry.css
--- a/htdocs/stc/entry.css	Wed Nov 25 03:56:46 2009 +0000
+++ b/htdocs/stc/entry.css	Wed Nov 25 04:06:39 2009 +0000
@@ -554,3 +554,9 @@ td.tabs {
 td.tabs {
     width:41%;
 }
+
+
+/* for entering the user tag */
+.userprompt {  padding: 0 1em 0.5em 1em; }
+.userprompt .submitbtncontainer {  margin-top: 1em; }
+.userprompt label { display: block; padding: 0.5em 0 0.1em 0; }
diff -r 0e9424044833 -r 13b9b8990773 htdocs/stc/fck/editor/plugins/livejournal/fckplugin.js
--- a/htdocs/stc/fck/editor/plugins/livejournal/fckplugin.js	Wed Nov 25 03:56:46 2009 +0000
+++ b/htdocs/stc/fck/editor/plugins/livejournal/fckplugin.js	Wed Nov 25 04:06:39 2009 +0000
@@ -7,11 +7,6 @@ LJUserCommand.GetState=function() {
     return FCK_TRISTATE_OFF; //we dont want the button to be toggled
 }
 
-// Check for allowed lj user characters
-LJUserCommand.validUsername = function(str) {
-    var pattern = /^\w{1,15}$/i;
-    return pattern.test(str);
-}
 
 LJUserCommand.Execute=function() {
     var username;
@@ -37,47 +32,135 @@ LJUserCommand.Execute=function() {
         }
     }
 
+    function do_insert( username, site ) {
+        var postData = {
+            "username" : username,
+            "site"     : site
+        };
+    
+        if (username == null) return;
+    
+        var url = window.parent.Site.siteroot + "/tools/endpoints/ljuser";
+    
+        var gotError = function(err) {
+            alert(err);
+        }
+    
+        var gotInfo = function (data) {
+            if (data.error) {
+                alert(data.error);
+                return;
+            }
+
+            if (!data.success) return;
+
+            if ( site ) 
+                data.ljuser = data.ljuser.replace(/<span.+?class=['"]?ljuser['"]?.+?>/,'<div class="ljuser" site="' + site + '">');
+            else 
+                data.ljuser = data.ljuser.replace(/<span.+?class=['"]?ljuser['"]?.+?>/,'<div class="ljuser">');
+
+            data.ljuser = data.ljuser.replace(/<\/span>/,'</div>');
+            FCK.InsertHtml(data.ljuser);
+            FCK.InsertHtml('&nbsp;')
+            if (selection != '') FCKSelection.Collapse();
+            FCK.Focus();
+        }
+    
+        var opts = {
+            "data": window.parent.HTTPReq.formEncoded(postData),
+            "method": "POST",
+            "url": url,
+            "onError": gotError,
+            "onData": gotInfo
+        };
+    
+        window.parent.HTTPReq.getJSON(opts);
+    }
+
     if (selection != '') {
         username = selection;
+        do_insert( username );
     } else {
-        username = prompt(window.parent.FCKLang.UserPrompt, '');
+        var DOM = window.parent.DOM;
+        var _textDiv = window.parent._textDiv;
+        var userPopup = new window.parent.LJ_IPPU( window.parent.FCKLang.UserPrompt );
+        userPopup.hide =   function() {
+            window.parent.LJ_IPPU.superClass.hide.apply(this);
+            DOM.removeEventListener( window.parent.document, "keyup", LJUserCommand.KeyUpHandler );
+        }
+
+
+        var inner = document.createElement( "div" );
+        DOM.addClassName( inner, "userprompt" );
+
+        var label = document.createElement( "label" );
+        label.appendChild( _textDiv( window.parent.FCKLang.UserPrompt_User ) );
+        label.setAttribute( "for", "userprompt-username" );
+        inner.appendChild( label );
+
+        var username = document.createElement( "input" );
+        username.name = "username";
+        username.id = "userprompt-username";
+        inner.appendChild( username );
+
+        label = document.createElement( "label" );
+        label.appendChild( _textDiv( window.parent.FCKLang.UserPrompt_Site ) );
+        label.setAttribute( "for", "userprompt-site" );
+        inner.appendChild( label );
+
+        var siteList = document.createElement( "select" );
+        siteList.name = "site";
+        siteList.id = "userprompt-site";
+        var option = new Option( "--", "" );
+        option.selected = "selected";
+        siteList.appendChild( option );
+        inner.appendChild( siteList );
+
+        for ( var i = 0; i < window.parent.FCKLang.UserPrompt_SiteList.length; i++ ) {
+            var site = window.parent.FCKLang.UserPrompt_SiteList[i];
+            var option = new Option( site.sitename, site.domain );
+            siteList.appendChild( option );
+        }
+
+        var btncont = document.createElement( "div" );
+        DOM.addClassName( btncont, "submitbtncontainer" );
+        var btn = document.createElement( "input" );
+        DOM.addClassName ( btn, "submitbtn" );
+        btn.type = "button";
+        btn.value = "Insert";
+        btncont.appendChild( btn );
+        inner.appendChild( btncont );
+
+        userPopup.setContentElement( inner );
+
+        userPopup.setAutoCenter( true, true );
+        userPopup.setDimensions( "15em", "auto" );
+        userPopup.show();
+        username.focus();
+
+        DOM.addEventListener( window.parent.document, "keyup", function(userPopup) { 
+            return  LJUserCommand.KeyUpHandler = function(e) {
+                var code = e.keyCode || e.which;
+                // enter
+                if ( code == 13 ) {            
+                    userPopup.hide();
+                    do_insert( username.value, siteList.value );
+                    return;
+                }
+                // escape
+                if ( code == 27 ) {
+                    userPopup.hide();
+                    return;
+                }
+            } }(userPopup)
+        );
+
+        DOM.addEventListener( btn, "click", function (e) {
+            userPopup.hide();
+            do_insert( username.value, siteList.value );
+        } );
     }
 
-    var postData = {
-        "username" : username
-    };
-    if (username == null) return;
-
-    var url = window.parent.Site.siteroot + "/tools/endpoints/ljuser.bml";
-
-    var gotError = function(err) {
-        alert(err);
-        return;
-    }
-
-    var gotInfo = function (data) {
-        if (data.error) {
-            alert(data.error);
-            return;
-        }
-        if (!data.success) return;
-        data.ljuser = data.ljuser.replace(/<span.+?class=['"]?ljuser['"]?.+?>/,'<div class="ljuser">');
-        data.ljuser = data.ljuser.replace(/<\/span>/,'</div>');
-        FCK.InsertHtml(data.ljuser);
-        FCK.InsertHtml('&nbsp;')
-        if (selection != '') FCKSelection.Collapse();
-        FCK.Focus();
-    }
-
-    var opts = {
-        "data": window.parent.HTTPReq.formEncoded(postData),
-        "method": "POST",
-        "url": url,
-        "onError": gotError,
-        "onData": gotInfo
-    };
-
-    window.parent.HTTPReq.getJSON(opts);
     return false;
 }
 
diff -r 0e9424044833 -r 13b9b8990773 htdocs/tools/endpoints/ljuser.bml
--- a/htdocs/tools/endpoints/ljuser.bml	Wed Nov 25 03:56:46 2009 +0000
+++ b/htdocs/tools/endpoints/ljuser.bml	Wed Nov 25 04:06:39 2009 +0000
@@ -2,6 +2,7 @@
 {
     use strict;
     use vars qw(%POST);
+    use DW::External::User;
     use LJ::Auth;
     use JSON;
 
@@ -15,18 +16,36 @@
     };
 
     my $username = $POST{'username'};
-    my $u = LJ::load_user($username);
+    my $site = $POST{site};
 
     my %ret;
 
     BML::set_content_type('text/javascript; charset=utf-8');
     BML::finish();
 
+    my $u;
+
+    if ( $site ) {
+        # verify that this is a proper site
+        $u = DW::External::User->new( user => $username, site => $site );
+        if ( $u ) {
+            $ret{userstr} = '<user site="' . $u->site->{domain} . '" name="' . $u->user . '">';
+            $ret{ljuser} = $u->ljuser_display;
+        }
+    }
+
+    unless ( $u ) {
+        $u = LJ::load_user( $username );
+        $ret{userstr} = "<user name=\"$username\">";
+        $ret{ljuser} = LJ::ljuser( $u );
+    }
+
+    # more general error message if we may have been trying to show an external site
+    return $err->("Invalid user or site") if $site && ! $u;
+
+    # more specific error message if we are loading a user on the site
     return $err->("No such user") unless $u;
-
-    $ret{ljuser} = LJ::ljuser($u);
-    $ret{userstr} = "<user name=\"$username\">";
-
+    
     sleep(1.5) if $LJ::IS_DEV_SERVER;
 
     $ret{success} = 1;
--------------------------------------------------------------------------------