blogjava-凯发k8网页登录

blogjava-凯发k8网页登录http://www.blogjava.net/chengang/  逝者如斯夫不舍昼夜zh-cnsat, 08 apr 2023 20:42:18 gmtsat, 08 apr 2023 20:42:18 gmt60《eclipse从入门到精通》随书光盘地址http://www.blogjava.net/chengang/archive/2017/12/29/432993.html陈刚陈刚fri, 29 dec 2017 07:37:00 gmthttp://www.blogjava.net/chengang/archive/2017/12/29/432993.htmlhttp://www.blogjava.net/chengang/comments/432993.htmlhttp://www.blogjava.net/chengang/archive/2017/12/29/432993.html#feedback0http://www.blogjava.net/chengang/comments/commentrss/432993.htmlhttp://www.blogjava.net/chengang/services/trackbacks/432993.html我的新博客地址: 

书的软件和代码放在百度网盘:




陈刚 2017-12-29 15:37
]]>
二级域名的java实现http://www.blogjava.net/chengang/archive/2010/12/29/341939.html陈刚陈刚wed, 29 dec 2010 15:19:00 gmthttp://www.blogjava.net/chengang/archive/2010/12/29/341939.htmlhttp://www.blogjava.net/chengang/comments/341939.htmlhttp://www.blogjava.net/chengang/archive/2010/12/29/341939.html#feedback0http://www.blogjava.net/chengang/comments/commentrss/341939.htmlhttp://www.blogjava.net/chengang/services/trackbacks/341939.htmlhttp://www.yowob.com ),其他涉及到为用户提供一个二级域名功能,实现方法如下:

(1)首先要在域名服务商端做一个泛域名解析. 我用的是godaddy.com,就新建一个a记录(host=*,point to指向我的服务器的ip),这样所有二级域名都会转到我的服务器来了

(2)接着在web.xml配一个自已写的域名过滤器,

    
        urlfilter
        com.yowob.commons.urlfilter
    

    
        urlfilter
        /*
    

过滤器的代码如下。这里先将二级域名和全球域名和用户id的映射,保存在一个数据表里, 然后访问进来时对地址做一个判断, 再取出对应的用户id. 再转一下就行了. 我的静态文件都在static目录,所以还加了一个static的判断。
比如: 用time对应用户id为6,则访问效果有 相同, 不过地址栏还是显示。
再比如:htttp://www.userdomain.com/board/21,这个是用户id为6的全球域名,访问效果也和上面一样。

package com.yowob.commons;

import java.io.ioexception;
import java.util.hashmap;
import java.util.list;
import java.util.map;

import javax.servlet.filter;
import javax.servlet.filterchain;
import javax.servlet.filterconfig;
import javax.servlet.servletexception;
import javax.servlet.servletrequest;
import javax.servlet.servletresponse;
import javax.servlet.http.httpservletrequest;

import org.apache.commons.lang.stringutils;
import org.apache.commons.lang.math.numberutils;
import org.apache.commons.logging.log;
import org.apache.commons.logging.logfactory;

import com.yowob.constants;
import com.yowob.dao.sitedao;
import com.yowob.dto.sitedto;

public class urlfilter implements filter {
    
private static final log log = logfactory.getlog(urlfilter.class);
    
private static final string domain_end = "."  constants.domain; //.you.com
    private static final map<string, long> name_map = new hashmap<string, long>();
    
private static final map<string, long> domain_map = new hashmap<string, long>();

    @override
    
public void init(filterconfig filterconfig) throws servletexception {
        log.info(
"------------------------------init");
        sitedao sitedao 
= new sitedao();
        list
<sitedto> list = sitedao.getall();
        
for (sitedto sitedto : list) {
            string name 
= sitedto.getname();
            
if (stringutils.isnotempty(name)) {
                name_map.put(name, sitedto.getid());
            }
            string domain 
= sitedto.getdomain();
            
if (stringutils.isnotempty(domain)) {
                domain_map.put(domain, sitedto.getid());
            }
        }
    }

    
public static void updatename(string oldvalue, string newvalue, long siteid) {
        
if (stringutils.equals(oldvalue, newvalue)) {
            
return;
        }
        
if (stringutils.isnotempty(oldvalue)) {
            name_map.remove(oldvalue);
        }
        
if (stringutils.isnotempty(newvalue)) {
            name_map.put(newvalue, siteid);
        }
    }

    
public static void updatedomain(string oldvalue, string newvalue, long siteid) {
        
if (stringutils.equals(oldvalue, newvalue)) {
            
return;
        }
        
if (stringutils.isnotempty(oldvalue)) {
            domain_map.remove(oldvalue);
        }
        
if (stringutils.isnotempty(newvalue)) {
            domain_map.put(newvalue, siteid);
        }
    }

    @override
    
public void destroy() {
        log.info(
"------------------------------destroy");
    }

    @override
    
public void dofilter(servletrequest servletrequest, servletresponse response, filterchain filterchain) throws ioexception, servletexception {
        httpservletrequest request 
= (httpservletrequest) servletrequest;
        string requesturi 
= request.getrequesturi();
        string servername 
= request.getservername().tolowercase();
        string realuri 
= getrealrequesturi(servername, requesturi);
        request.getrequestdispatcher(realuri).forward(request, response);
    }

    
private string getrealrequesturi(string servername, string requesturi) {
        
if (constants.www_domain.equals(servername) || requesturi.startswith("/static/"|| constants.domain.equals(servername)) {
            
return requesturi;
        }
        
if (servername.endswith(domain_end)) {
            string seconddomain 
= servername.substring(0, servername.indexof("."));
            
//网站id
            if (numberutils.isnumber(seconddomain))
                
return geturi(seconddomain, requesturi);
            
//网站英文名
            long siteid = name_map.get(seconddomain);
            
if (siteid == null) {
                
//保留的二级域名
                if (constants.isprivateseconddomain(seconddomain)) {
                    
return requesturi;
                }
                
return "/message?msg=不存在二级域名"  seconddomain;
                
//                throw new runtimeexception("do not exist second domain: "   seconddomain);
            }
            
return geturi(siteid  "", requesturi);
        }
        
//域名
        long siteid = domain_map.get(servername);
        
if (siteid == null) {
            
return requesturi;
        } 
else {
            
return geturi(siteid  "", requesturi);
        }
    }

    
private static string geturi(string siteid, string requesturi) {
        
if (requesturi.equals("/")) {
            
return "/"  siteid;
        } 
else {
            
return "/"  siteid  requesturi;
        }
    }

}


其他一些小技巧:
(1)为了便于本机测试,可以修改windows 的hosts文件。我的如下:
127.0.0.1       localhost
127.0.0.1       you.com
127.0.0.1       www.you.com
127.0.0.1       time1.you.com
127.0.0.1       time2.you.com
127.0.0.1       6.you.com
127.0.0.1       www.bobo.com

(2)web页的各种地址则要注意相对路径的问题。主要考虑
首先设置,或其中地址最后要加一个/
然后页面中其他地址前面不加/,就是相对地址(以地址栏为基础)。加上/,则是绝对地址。


陈刚 2010-12-29 23:19
]]>
vim的常用插件 配置文件 资料http://www.blogjava.net/chengang/archive/2007/10/18/153970.html陈刚陈刚thu, 18 oct 2007 10:15:00 gmthttp://www.blogjava.net/chengang/archive/2007/10/18/153970.htmlhttp://www.blogjava.net/chengang/comments/153970.htmlhttp://www.blogjava.net/chengang/archive/2007/10/18/153970.html#feedback7http://www.blogjava.net/chengang/comments/commentrss/153970.htmlhttp://www.blogjava.net/chengang/services/trackbacks/153970.html 我把vim的常用插件,自己用的配置文件,收罗的一些资料一并打包了,省得初用vim的人找来找去浪费时间。





在ubuntu7.10中的gvim出现乱码,这时需要在主目录下的“.vimrc”文件中加上定义字体的一句。我用的是“微软雅黑”字体所以此句为:
set guifont=yahei\ consolas\ hybrid\ 10
注意:字体名中有空格的,用斜杠分开,而且斜杠后面一定要有一个空格。10是字体大小,前面有一个空格。


陈刚 2007-10-18 18:15
]]>
个性化页面布局的设计思考与rails初步实现http://www.blogjava.net/chengang/archive/2007/10/11/151900.html陈刚陈刚wed, 10 oct 2007 16:00:00 gmthttp://www.blogjava.net/chengang/archive/2007/10/11/151900.htmlhttp://www.blogjava.net/chengang/comments/151900.htmlhttp://www.blogjava.net/chengang/archive/2007/10/11/151900.html#feedback0http://www.blogjava.net/chengang/comments/commentrss/151900.htmlhttp://www.blogjava.net/chengang/services/trackbacks/151900.html
这个设计其实很简单,就是“引擎 配置“--主体页面只定义一个rthml,可以把它看做页面引擎,然后用一个配置文件指定了页面所应具有的模块和数据。 页面模块就象一个个装有数据的盒子,通过“页面引擎 配置文件”把这些盒子组合起来,象搭积木一样。页面引擎是各用户共用的,配置文件是各用户独有的,这样一装配起来,就形成了用户的个性化页面。

剩下的重点就是怎么定义配置文件。首先是要划清配置文件的责任界线----它只负责定义盒子里的数据,还有盒子的嵌套关系,而大小和位置等布局方面则全部交给css去负责。

上面是初步想法,下面看看具体实现,代码仅供参考

以下是某个用户的配置文件(我没用xml,而是用yaml)。board_1是指id=1这个栏目所用的配置定义。topcontent是一个
的id值,我把每个栏目的页面分成topcontent顶、sidecontent边(左或右由css决定)、primarycontent 主要、bottomcontent底。topic是指添加一个模块(盒子),显示一个主题内容。和topic类似是还有显示图像的image、显示主题列 表的topics、显示分类列表的categories等等等等。它们各有不同的属性值,比如topic模块,它需要定指它的主题id,以及它所用的 view(topics/_show_hot.rhtml  or  topics/_show.rhtml等等)。

(虽然这个配置文件抽象得还不够,但这样子已经可以解决我的需要了,那
暂时这样先了。)

template.yml
 
  1. board_2:  
  2.   
  3. board_1:  
  4. - topcontent:  
  5.   - topic:  
  6.       topic_id: 7  
  7.       view: topics/show_hot  
  8. - sidecontent:  
  9.   - image:  
  10.       url: /images/news.jpg  
  11.   - categories:  
  12.       board: 5  
  13.       view: tree  
  14.   - topics:  
  15.       board: 5  
  16.       per_page: 4  
  17.       view: index_simple  
  18.   - topics:  
  19.       board: 6  
  20. - primarycontent:  
  21.   - topics:  
  22.       board: 4  
  23.       view: index  
  24.   - topic:  
  25.       topic_id: 7  
  26.       view: util/box  
  27.   
  28. board_3:  

然后在controller里把配置文件读入,再转化成模型类。我把各个界面模块看做一个个盒子box
这是它的顶级box
ruby 代码
 
  1. class box  
  2.   attr_accessor :html_id:view:boxes  
  3.   def initialize
  4.     @boxes=[]  
  5.   end  
  6. end  

这是topic模块的
ruby 代码
 
  1. class topicbox < box  
  2.   attr_accessor :topic_id  
  3. end  

这是image模块的
ruby 代码
 
  1. class imagebox < box  
  2.   attr_accessor :url  
  3. end    

.....等 等, 其他的box子类大同小异

然后在一个controller里把这些配置信息转成box模型类
ruby 代码
 
  1. templates =  yaml::load(file.read("public/uploads/#{user_id}/config/template.yml"))
  2. template = templates.find{|o| o[0]=="board_#{@board.id}" }  
  3. args = template[1]  
  4.   
  5. @boxes = []  
  6. args.each do |arg1_hash|  
  7.   arg1_hash.each do |key1, value1|  
  8.     board_box = boardbox.new  
  9.     board_box.html_id = key1  
  10.     @boxes << board_box  
  11.     value1.each do |arg2_hash|  
  12.       arg2_hash.each do |key2, value2|  
  13.         case key2  
  14.         when 'topics'  
  15.           box = topicsbox.new  
  16.           box.board_id = value2['board']  
  17.           box.per_page = value2['per_page']||2  
  18.           box.view = value2['view']||'index_simple'  
  19.           board_box.boxes << box   
  20.         when 'categories'  
  21.           box = categoriesbox.new  
  22.           box.board_id = value2['board']  
  23.           box.view = value2['view']||'list'  
  24.           board_box.boxes << box   
  25.         when 'image'  
  26.           box = imagebox.new  
  27.           box.url = value2['url']  
  28.           board_box.boxes << box   
  29.         when 'topic'  
  30.           box = topicbox.new  
  31.           box.topic_id = value2['topic_id']  
  32.           box.view = value2['view']||'util/box'  
  33.           board_box.boxes << box   
  34.         end  
  35.       end  
  36.     end  
  37.   end  
  38. end 

最后是它页面引擎(逻辑代码和页面代码混在一起,比较丑陋)
ruby 代码
 
  1. <% @boxes.each do |box1| %>  
  2. "<%=box1.html_id%>">  /span>
  3.   <% box1.boxes.each do |box2|  
  4.        p1 box2.class.to_s  
  5.   
  6.       case box2.class.to_s  
  7.       when 'topicsbox'  
  8.         board_id = box2.board_id  
  9.         if board_id  
  10.           board = board.find(board_id)  
  11.           topics = topic.by_board_id(board_id, :per_page => box2.per_page)   
  12.           %>  
  13.           <%= render(:partial => "topics/#{box2.view}":locals => {:title =>board.title, :topics => topics })%>  
  14.         <%end  
  15.       when 'categoriesbox'  
  16.         board_id = box2.board_id  
  17.         if board_id  
  18.           board = board.find(board_id)  
  19.           categories = board.categories  
  20.           %>  
  21.           <%= render :partial => "categories/#{box2.view}":locals => {:board =>board, :categories => categories } %>  
  22.         <%end%>  
  23.       <%when 'imagebox'%>  
  24.         <%= box_tag :header=>false%>  
  25.           <%=image_tag(box2.url, :border => 0) %>  
  26.         <%= end_box_tag %>  
  27.       <%when 'topicbox'  
  28.         topic = topic.find(box2.topic_id) %>  
  29.         <%=render(:partial => "#{box2.view}":locals => {:title =>topic.title, :content => topic.content, :topic => topic })%>  
  30.       <%end  
  31.   end%> 
 

这样,以后想在页面上增加删除什么模块,修改配置文件就行了。当然给用户用,还必须得用ajax来写个gui界面,总不能让用户手工去改配置文件吧。


陈刚 2007-10-11 00:00
]]>抽取fckeditor的浏览图片功能http://www.blogjava.net/chengang/archive/2007/09/26/148412.html陈刚陈刚wed, 26 sep 2007 10:49:00 gmthttp://www.blogjava.net/chengang/archive/2007/09/26/148412.htmlhttp://www.blogjava.net/chengang/comments/148412.htmlhttp://www.blogjava.net/chengang/archive/2007/09/26/148412.html#feedback2http://www.blogjava.net/chengang/comments/commentrss/148412.htmlhttp://www.blogjava.net/chengang/services/trackbacks/148412.html
文/陈刚 转载请保留出处
在阅读fckeditor的源码之后,做如下处理。

1. 新增两个javascript函数。
var currentimagetextid;

//fckeditor的文件浏览窗关闭后,会调用此函数,并把所选图片的url传入。
function set{
  document.getelementbyid(currentimagetextid).value
=url;
}

//imagetextid: 图片文本框的id值
//
uploadpath: 服务器的图片目录
//
type: 浏览类型,值可为image/flash/file/media,如果为空字串,则表示浏览所有类型的文件
function openimagebrowser(imagetextid, uploadpath, type ) {
  currentimagetextid 
= imagetextid;
  window.open('
/javascripts/fckeditor/editor/filemanager/browser/default/browser.html?uploaded='uploadpath'&type='type'&connector=/fckeditor/command','browse/upload images','toolbar=no,status=no, resizable=yes,dependent=yes, scrollbars=yes,width=600,height=400')
}

2.在view中这样使用
标志图片:
<
input id="topic_image" name="topic[image]" size="30" type="text">
<
input value="浏览服务器" onclick="openimagebrowser('topic_image', '/uploads/s<%= params[:user_id]%>', 'image')" type="button">




陈刚 2007-09-26 18:49
]]>
让rails版的fckeditor支持动态设置上传目录http://www.blogjava.net/chengang/archive/2007/09/26/148114.html陈刚陈刚wed, 26 sep 2007 02:13:00 gmthttp://www.blogjava.net/chengang/archive/2007/09/26/148114.htmlhttp://www.blogjava.net/chengang/comments/148114.htmlhttp://www.blogjava.net/chengang/archive/2007/09/26/148114.html#feedback5http://www.blogjava.net/chengang/comments/commentrss/148114.htmlhttp://www.blogjava.net/chengang/services/trackbacks/148114.html
文/陈刚 转载请保留出处
1.修改fckeditor_controller.rb,把它那几个private方法修改如下:
  
  
private
  def current_directory_path
    base_dir 
= "#{rails_root}/public"

    #todo 在创建用户时,就建立好目录。这时可以去掉这部份代码,提高运行效率。
    (
"#{params[:uploaded]||uploaded}/#{params[:type]}").split('/').each do |s|
    next 
if s==''
        base_dir 
= '/'  s
        dir.mkdir(base_dir,
0775) unless file.exists?(base_dir)
    end
    
    check_path(
"#{base_dir}#{params[:currentfolder]}")
  end
  
  def upload_directory_path
    uploaded 
= @request.relative_url_root.to_s"#{params[:uploaded]||uploaded}/#{params[:type]}"
    
"#{uploaded}#{params[:currentfolder]}"
  end
  
  def check_file(file)
    # check that the file is a tempfile object
    unless 
"#{file.class}" == "tempfile" || "#{file.class}" == "stringio"
      @errornumber 
= 403
      
throw exception.new
    end
    file
  end
  
  def check_path(path)
    exp_path 
= file.expand_path path
    
if exp_path !~ %r[^#{file.expand_path(rails_root)}/public#{params[:uploaded]||uploaded}]
      @errornumber 
= 403
      
throw exception.new
    end
    path
  end

另外,它前面的常量uploaded_root也没用了,可以删掉。


2. 在上面的代码中params[:uploaded]是关键,它就是我们动态定义的上传目录。该值来自于fckeditor的一些html页面,它是通过get参数传入的。修改browser.html文件(如下粗体部份),在它的url请求中把我们定义目录加入到get参数列中,这样它就可以传到fckeditor_controller.rb里了


var sserverpath 
= geturlparam( 'serverpath' ) ;
if ( sserverpath.length > 0 )
    oconnector.connectorurl 
= 'serverpath='  escape( sserverpath )  '&' ;

var suploaded 
= geturlparam( 'uploaded' ) ;
if ( suploaded.length > 0 )
    oconnector.connectorurl 
= 'uploaded='  escape( suploaded )  '&'
 ;

oconnector.resourcetype        
= geturlparam( 'type' ) ;
oconnector.showalltypes        
= ( oconnector.resourcetype.length == 0 ) ;


3.  上面
的geturlparam( 'uploaded' ) 的值来自于fckcustom.js。修改fckcustom.js(如下粗体部份),把uploaded加入到get参数列中。

// change for apps hosted in subdirectory
fckrelativepath 
= '';

// don't change these
fckconfig.linkbrowserurl = fckconfig.basepath  'filemanager/browser/default/browser.html?connector='fckrelativepath'/fckeditor/command';
fckconfig.imagebrowserurl 
= fckconfig.basepath  'filemanager/browser/default/browser.html?uploaded='fckconfig.uploaded'&type=image&connector='fckrelativepath'/fckeditor/command';
fckconfig.flashbrowserurl 
= fckconfig.basepath  'filemanager/browser/default/browser.html?uploaded='fckconfig.uploaded'&type=flash&connector='fckrelativepath'/fckeditor/command';

fckconfig.linkuploadurl 
= fckrelativepath'/fckeditor/upload';
fckconfig.imageuploadurl 
= fckrelativepath'/fckeditor/upload?type=image&uploaded='fckconfig.uploaded;
fckconfig.flashuploadurl 
= fckrelativepath'/fckeditor/upload?type=flash&uploaded='fckconfig.uploaded;
fckconfig.allowquerystringdebug 
= false;
fckconfig.spellchecker 
= 'spellerpages';

// only change below here
fckconfig.skinpath 
= fckconfig.basepath  'skins/silver/';
fckconfig.autodetectlanguage 
= false ;
fckconfig.defaultlanguage 
= 'zh-cn' ;
fckconfig.fontnames 
= '微软雅黑;宋体;黑体;隶书;楷体_gb2312;arial;comic sans ms;courier new;tahoma;times new roman;verdana' ;

fckconfig.toolbarsets[
"simple"= [
    [
'source','-','fitwindow','preview','-','templates'],
    [
'pastetext','pasteword'],
    [
'undo','redo','find','replace'],
    
'/',
    [
'removeformat','bold','italic','underline','strikethrough'],
    [
'orderedlist','unorderedlist','outdent','indent'],
    [
'justifyleft','justifycenter','justifyright','justifyfull'],
        [
'textcolor','bgcolor'],
    [
'link','unlink','anchor'],
    [
'image','flash','table','rule','smiley'],
    
'/',
    [
'style','fontformat','fontname','fontsize']
] ;

4. 上面fckconfig.uploaded的值来自于fckeditor.rb。在fckeditor.rb中加入一句(如下粗体所示)。
      javascript_tag( "var ofckeditor = new fckeditor('#{id}', '#{width}', '#{height}', '#{toolbarset}');\n"
                      
"ofckeditor.basepath = \"#{base_path}\"\n"
                      "ofckeditor.config['customconfigurationspath'] = '../../fckcustom.js';\n"
                      
"ofckeditor.config['uploaded'] = '#{options[:path]}';\n"
                      
"ofckeditor.replacetextarea();\n")                         

5.不过上面ofckeditor.config['uploaded']的值要传到fckcustom.js的fckconfig.uploaded里,还需要修改fckeditorcode_gecko.js和fckeditorcode_ie.js(这两个文件对javascript进行了压缩处理,修改起来较难操作)。我是参考了ofckeditor.config['customconfigurationspath'] 这个参数的载入实现,才找到这种鸟不生蛋的地方。搜索这两个文件的关键字customconfigurationspath,找到如下一行,然后加入一个else if判断(如下粗体所示)。
if (d=='customconfigurationspath') fckconfig[d]=e;else if (d=='uploaded') fckconfig[d]=e;else if (e.tolowercase()=="true"this.pageconfig[d]=true;


6.最后在fckeditor.rb里的#{options[:path]}来自于我们前台的view了。如下粗体所示,把标准的fckeditor_textarea新增加了一个参数,其中params[:user_id]是把用户的id值做为目录名。这样就实现了动态改变fckeditor的上传目录。

<%=fckeditor_textarea(:topic, :content, :ajax => true, :toolbarset => 'simple', :height => '400px',  :path => "/uploads/#{params[:user_id]}"%>


修改完后需要重启web服务,最后别忘记把public/javascripts/fckeditor和vendor/plugins/fckeditor/public/javascripts同步一下,原因见http://www.blogjava.net/chengang/archive/2007/09/24/147867.html


陈刚 2007-09-26 10:13
]]>
定制fckeditor,以及使其中文化http://www.blogjava.net/chengang/archive/2007/09/24/147867.html陈刚陈刚mon, 24 sep 2007 10:24:00 gmthttp://www.blogjava.net/chengang/archive/2007/09/24/147867.htmlhttp://www.blogjava.net/chengang/comments/147867.htmlhttp://www.blogjava.net/chengang/archive/2007/09/24/147867.html#feedback0http://www.blogjava.net/chengang/comments/commentrss/147867.htmlhttp://www.blogjava.net/chengang/services/trackbacks/147867.html
文/陈刚 
首先,我们来看看fckeditor在rails中的运行特性,其插件主要是安装在vendor/plugins/fckeditor。主要的代码在vendor/plugins/fckeditor/public/javascripts,其中fckcustom.js是配置文件,另外更深一层的子目录fckeditor中还有一个fckconfig.js也是配置文件。fckcustom.js配置的优先顺序大于fckconfig.js,因此一般修改fckcustom.js就可以了,不必去动fckconfig.js。

在启动webrick( ruby script/server)时,会自动把vendor/plugins/fckeditor/public/javascripts的内容复制到public/javascripts目录。因此如果你修改了fckeditor的配置文件之后,需要把复制到public/javascripts目录的fckeditor相关文件删除掉,然后再重启webrick。当然,你也可以直接修改public/javascripts目录的fckeditor的缓存的配置文件,这样不必重启webrick,就可以立即看到修改效果。不过建议你在完成修改后,同时也要更新vendor/plugins/fckeditor/public/javascripts下的配置文件,毕竟public/javascripts里的应该算是临时文件。


1.中文化

在fckcustom.js里加入两项(粗体显示)
fckconfig.skinpath = fckconfig.basepath  'skins/silver/';
fckconfig
.autodetectlanguage = false ;
fckconfig
.defaultlanguage = 'zh-cn'
 ;

2. 定制fckeditor的工具栏
修改fckcustom.js里的如下项目,增删改自便。
fckconfig.toolbarsets["simple"= [   。。。 。。。

这里要注意一点,有些网上文章把:toolbarset写成了:toolbarkit,这是错误的。如果你发现对工具栏的配置不起作用,那么要检查一下。正确的写法如下:
<%=fckeditor_textarea(:topic, :content, :ajax => true, :toolbarset => 'simple', :width => '100%', :height => '300px'%>








陈刚 2007-09-24 18:24
]]>
error_messages_for的中文化http://www.blogjava.net/chengang/archive/2007/09/19/146548.html陈刚陈刚wed, 19 sep 2007 09:35:00 gmthttp://www.blogjava.net/chengang/archive/2007/09/19/146548.htmlhttp://www.blogjava.net/chengang/comments/146548.htmlhttp://www.blogjava.net/chengang/archive/2007/09/19/146548.html#feedback0http://www.blogjava.net/chengang/comments/commentrss/146548.htmlhttp://www.blogjava.net/chengang/services/trackbacks/146548.htmlapplicationhelper
文/陈刚  www.chengang.com.cn  转载请声明出处

  def error_messages_for(*params)
    
#add by glchengang
    key_hash = {}
    
if params.first.is_a?(hash)
      key_hash 
=  params.first
      params
.delete_at(0)
    end
    
#add end

    options 
= params.last.is_a?(hash) ? params.pop.symbolize_keys : {}
    objects 
= params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
    count   
= objects.inject(0) {|sum, object| sum  object.errors.count }
    
unless count.zero?
      html 
= {}
      [
:id, :class].each do |key|
        
if options.include?(key)
          value 
= options[key]
          html[key] 
= value unless value.blank?
        
else
          html[key] 
= 'errorexplanation'
        end
      end
      
# change by glchengang
      header_message = "有#{count}个错误"
#       header_message = "#{pluralize(count, 'error')} prohibited this #{(options[:object_name] || params.first).to_s.gsub('_', ' ')} from being saved"
      
      #add by glchengang

      error_messages = objects.map do |object|
        temp 
= []
        object
.errors.each do |attr, msg|
          temp 
<< content_tag(:li, (key_hash[attr] || attr)  msg) 
        end
        temp
      end
      
#add end

#        error_messages = objects.map {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }

      content_tag(:div,
        content_tag(options[
:header_tag] || :h2, header_message) <<
#           content_tag(:p, 'there were problems with the following fields:') <<
          content_tag(:ul, error_messages),
        html
      )
    
else
      
''
    end
  end


使用依然兼容老的方式,你也可以传入一个哈希表,把模型字段显示成对应的中文,示例如下:
<%= 
= {'username'=>'用户名', 'password'=>'密码'}
error_messages_for h
, :user
%>

另外,还要在environment.rb的最后插入以下代码:

errors = activerecord::errors.default_error_messages
errors[
:taken] = '已经被使用'
errors[
:blank] = '不能为空'



陈刚 2007-09-19 17:35
]]>
让will_paginate的分页支持ajaxhttp://www.blogjava.net/chengang/archive/2007/09/02/142077.html陈刚陈刚sun, 02 sep 2007 07:42:00 gmthttp://www.blogjava.net/chengang/archive/2007/09/02/142077.htmlhttp://www.blogjava.net/chengang/comments/142077.htmlhttp://www.blogjava.net/chengang/archive/2007/09/02/142077.html#feedback14http://www.blogjava.net/chengang/comments/commentrss/142077.htmlhttp://www.blogjava.net/chengang/services/trackbacks/142077.html
文/陈刚 (www.chengang.com.cn)
但一直搜不到它支持ajax分面的方法 ,于是我参考它分页方法的源代码(位于:vendor/plugins/will_paginate/lib/will_paginate/view_helpers.rb),稍微改写,变成了一个支持ajax的分页方法。以下代码复制到application_helper里即可。


  
#-----------------------------------------
  # will_paginate插件的ajax分页
  #-----------------------------------------
  @@pagination_options = { :class => 'pagination',
        
:prev_label   => '上一页',
        
:next_label   => '下一页',
        
:inner_window => 4, # links around the current page
        :outer_window => 1, # links around beginning and end
        :separator    => ' ', # single space is friendly to spiders and non-graphic browsers
        :param_name   => :page,
        
#add by chengang
        :update =>nil, #ajax所要更新的html元素的id
        :url_suffix => ''  #url的后缀,主要是为了补全rest所需要的url
        #add end
        }
  mattr_reader 
:pagination_options

  def will_paginate_remote(entries 
= @entries, options = {})
    total_pages 
= entries.page_count

    
if total_pages > 1
      options 
= options.symbolize_keys.reverse_merge(pagination_options)
      page
, param = entries.current_page, options.delete(:param_name)
      
      inner_window
, outer_window = options.delete(:inner_window).to_i, options.delete(:outer_window).to_i
      
#add by chengang
      update =  options.delete(:update)
      suffix 
=  options.delete(:url_suffix)
      url 
= request.env['path_info'
      url 
= suffix if suffix
      
#add end

      
min = page - inner_window
      
max = page  inner_window
      
if max > total_pages then min -= max - total_pages
      elsif 
min < 1  then max  = 1 - min
      
end
      
      
current   = min..max
      beginning 
= 1..(1  outer_window)
      tail      
= (total_pages - outer_window)..total_pages
      visible   
= [beginning, current, tail].map(&:to_a).flatten.sort.uniq
      links
, prev = [], 0

      visible
.each do |n|
        
next if n < 1
        
break if n > total_pages

        unless n 
- prev > 1
          
prev = n
          
#change by chengang
          text = (n==page ? n : "[#{n}]")
          links 
<< page_link_remote_or_span((n != page ? n : nil), 'current', text, param, update, url)
        
else
          
prev = n - 1
          links 
<< ''
          redo
        
end
      
end
      
      
#change by chengang
      links.unshift page_link_remote_or_span(entries.previous_page, 'disabled', options.delete(:prev_label), param, update, url)
      links
.push    page_link_remote_or_span(entries.next_page,     'disabled', options.delete(:next_label), param, update, url)
      
#change end

      content_tag 
:div, links.join(options.delete(:separator)), options
    
end
  
end
  
protected

  def page_link_remote_or_span(page
, span_class, text, param, update, url)
    unless page
      content_tag 
:span, text, :class => span_class
    
else
      link_to_remote text
, :update => update, :url => "#{url}?#{param.to_sym}=#{page}", :method=>:get
    
end
  
end


在view中的使用如下所示:
          <%=will_paginate_remote @topics, :update => 'topiclist', :url_suffix => url_suffix%>




陈刚 2007-09-02 15:42
]]>
在rails中使用fckeditor插件实现web富文本编辑http://www.blogjava.net/chengang/archive/2007/08/25/139287.html陈刚陈刚sat, 25 aug 2007 08:44:00 gmthttp://www.blogjava.net/chengang/archive/2007/08/25/139287.htmlhttp://www.blogjava.net/chengang/comments/139287.htmlhttp://www.blogjava.net/chengang/archive/2007/08/25/139287.html#feedback2http://www.blogjava.net/chengang/comments/commentrss/139287.htmlhttp://www.blogjava.net/chengang/services/trackbacks/139287.html
文/陈刚  (www.chengang.com.cn)

环境:ubuntu linux 7.0.4    ruby 1.8.5 rails 1.2.3 fckeditor 0.4.1

直接从它的subversion库里取得该rails插件。先进入到你的项目根目录,再执行如下命令
ruby script/plugin install svn://rubyforge.org/var/svn/fckeditorp/trunk/fckeditor

其他说明:
(1)你的linux必须先安装了subversion。(ubuntu里用新立得搜subversion即得)
(2)把命令中的install 改为 destory,可以删除安装。
(3)我取到的是2007年4月份最后更新的, v 0.4.1版
(4)fckeditor安装在项目根目录下的vendor/plugins/fckeditor 里,
(5)vendor/plugins/fckeditor里的readme很值得一读,我碰到ajax问题,查了所以网上的中文资料都没有提到,在这个readme却有。


用如下语句在页面里含入它的javascript库
<%= javascript_include_tag :fckeditor %>  

<%= javascript_include_tag "fckeditor/fckeditor" %>


在需要富文本的form表单用如下语句生成一个富文件编辑框:
<%= fckeditor_textarea("topic""content", :toolbarset => 'simple', :width => '100%', :height => '200px') %>

说明:topic对应模型对象,content对应它的字段。也就是要求当前页要有@topic这个实例变量。


如果是用了ajax,则需要在form_remote_tag加上一个before项
  <%= form_remote_tag(:update => update,
                      :before 
=> fckeditor_before_js('topic', 'content'),
                      :url 
=> {:controller => 'topics', :action => 'create', :template => 'show'} )%>

并且富文件编辑框要加一个ajax=true的选项:
<%= fckeditor_textarea(:topic, :content, :ajax => true:toolbarkit => 'simple', :width => '100%', :height => '600px') %>





在使上传图片的功能时碰到了错误。弹出出alert对话框,显示:error on file upload.error number: 403

在日志里显示如下,表面上看好象是路由配置的问题

actioncontroller::routingerror (no route found to match "/fckblank.html" with {:method=>:get}):
/var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1292:in `recognize_path'
/var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1282:in `recognize'
/var/lib/gems/1.8/gems/rails-1.2.3/lib/dispatcher.rb:40:in `dispatch'
/var/lib/gems/1.8/gems/rails-1.2.3/lib/webrick_server.rb:113:in `handle_dispatch'
/var/lib/gems/1.8/gems/rails-1.2.3/lib/webrick_server.rb:79:in `service'
/usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
/usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
/usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
/usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'


最后在http://blog.caronsoftware.com/articles/2006/12/03/fckeditor-0-4-0-released#comment-1745找到了答案,这是一个bug

解决方法 :

修改:vendor/plugins/fckeditor/app/controller/fckeditor_controller.rb
将原来的

unless "#{file.class}" == "tempfile"

改为
unless "#{file.class}" == "tempfile" || "#{file.class}" == "stringio"





陈刚 2007-08-25 16:44
]]>
网站地图