[转载]Create subgrid with master datagrid - jQuery EasyUI

mikel阅读(1448)

[转载]Create subgrid with master datagrid – jQuery EasyUI.

Use the detail view of datagrid, users can expand a row to show additional details. As any content can be loaded as the row details, the subgrid can be dynamically loaded also. This tutorial will show you how to create a subgrid with master datagrid.

Step 1: Create Master DataGrid

  1. <table id=“dg” style=“width:700px;height:250px” url=“datagrid22_getdata.php” title=“DataGrid – SubGrid” singleselect=“true” fitcolumns=“true”>
  2. <thead>
  3. <tr>
  4. <th field=“itemid” width=“80”>Item ID</th>
  5. <th field=“productid” width=“100”>Product ID</th>
  6. <th field=“listprice” align=“right” width=“80”>List Price</th>
  7. <th field=“unitcost” align=“right” width=“80”>Unit Cost</th>
  8. <th field=“attr1” width=“220”>Attribute</th>
  9. <th field=“status” align=“center” width=“60”>Status</th>
  10. </tr>
  11. </thead>
  12. </table>

Step 2: Set Detail View to show subgrid

To use the detail view, remember to include the view script file to your page header.

  1. <script type=“text/JavaScript src=“http://www.jeasyui.com/easyui/datagrid-detailview.js”></script>
  1. $(‘#dg’).datagrid({
  2. view: detailview,
  3. detailFormatter:function(index,row){
  4. return ‘<div style=”padding:2px”><table id=”ddv-‘ + index + ‘”></table></div>’;
  5. },
  6. onExpandRow: function(index,row){
  7. $(‘#ddv-‘+index).datagrid({
  8. url:‘datagrid22_getdetail.php?itemid=’+row.itemid,
  9. fitColumns:true,
  10. singleSelect:true,
  11. rownumbers:true,
  12. loadMsg:,
  13. height:‘auto’,
  14. columns:[[
  15. {field:‘orderid’,title:‘Order ID’,width:100},
  16. {field:‘quantity’,title:‘Quantity’,width:100},
  17. {field:‘unitprice’,title:‘Unit Price’,width:100}
  18. ]],
  19. onResize:function(){
  20. $(‘#dg’).datagrid(‘fixDetailRowHeight’,index);
  21. },
  22. onLoadSuccess:function(){
  23. setTimeout(function(){
  24. $(‘#dg’).datagrid(‘fixDetailRowHeight’,index);
  25. },0);
  26. }
  27. });
  28. $(‘#dg’).datagrid(‘fixDetailRowHeight’,index);
  29. }
  30. });

When users click expand button(‘+’), the ‘onExpandRow’ event will be triggered. We create a new subgrid with tree columns. Remember to call ‘fixDetailRowHeight’ method for master datagrid when subgrid load data successfully or resize.

Step 3: The Server Code

datagrid22_getdata.php
  1. $result = array();
  2. include ‘conn.php’;
  3. $rs = mySQL_query(“select * from item where itemid in (select itemid from lineitem)”);
  4. $items = array();
  5. while($row = mySQL_fetch_object($rs)){
  6. array_push($items, $row);
  7. }
  8. echo json_encode($items);
datagrid22_getdetail.php
  1. $itemid = $_REQUEST[‘itemid’];
  2. include ‘conn.php’;
  3. $rs = mysql_query(“select * from lineitem where itemid=‘$itemid’“);
  4. $items = array();
  5. while($row = mysql_fetch_object($rs)){
  6. array_push($items, $row);
  7. }
  8. echo json_encode($items);

Download the EasyUI example:

[转载]使用 jQuery Uploader 显示文件上传进度

mikel阅读(1093)

[转载]使用 jQuery Uploader 显示文件上传进度 – 麦丝平方 – 博客园.

上传大文件的时候, 我们都希望可以向用户显示上传的进度, 那么这里介绍的就是使用 JQuery Uploader 来实现这样的效果.

请到 Download 下载资源JQueryElement 示例下载一节下载示例代码

本文将说明 Uploader 控件的功能以及使用过程中的注意事项和技巧, 目录如下:

* 准备

* 创建保存页面

* 添加 FileUpload 控件

* 设置 EnableSessionState

* 调用 Uploader 的 Save 方法

* 创建获取进度的页面

* 创建上传页面

* 设置保存页面

* 设置获取进度的页面

* 上传

* 隐藏保存页面

准备

请确保已经在 Download 下载资源 中的 JQueryElement.dll 下载一节下载 jQueryElement 最新的版本.

请使用指令引用如下的命名空间:

<%@ Register Assembly="zoyobar.shared.panzer.JQueryElement"
    Namespace="zoyobar.shared.panzer.ui.jqueryui.plusin"
    TagPrefix="je" %>
<%@ Register Assembly="zoyobar.shared.panzer.JQueryElement"
    Namespace="zoyobar.shared.panzer.web.jqueryui"
    TagPrefix="je" %>

除了命名空间, 还需要引用 jQueryUI 的脚本和样式, 在 Download 下载资源JQueryElement.dll 下载一节下载的压缩包中包含了一个自定义样式的 jQueryUI, 如果需要更多样式, 可以在 http://jqueryui.com/download 下载:除了命名空间, 还需要引用 jQueryUI 的脚本:

<link type="text/css" rel="stylesheet" href="[样式路径]/jquery-ui-<version>.custom.css" />
<script type="text/javascript" src="[脚本路径]/jquery-<version>.min.js"></script>
<script type="text/javascript" src="[脚本路径]/jquery-ui-<version>.custom.min.js"></script>

创建保存页面

保存页面是一个简单的页面, 主要完成文件的保存工作, 保存页面不会自己提交, 而是由上传页面提交.

添加 FileUpload 控件

首先, 为保存页面添加 FileUpload 控件:

<form id="formFileUpload" runat="server">
上传:&nbsp;<asp:FileUpload ID="file" runat="server" />
</form>

也可以添加 type 属性为 file 的 input 元素:

<form id="formFileUpload" runat="server" enctype="multipart/form-data">
上传:&nbsp;<input type="file" id="file" runat="server" />
</form>

如果使用 input 元素, 则可能需要设置 form 的 enctype 属性为 multipart/form-data.

设置 EnableSessionState

需要设置保存页面的 EnableSessionState 为 ReadOnly, 这样可以在保存页面保存文件时, 请求获取进度的页面. 这主要是由于, ASP.NET 顺序执行可以读写 Session 的页面:

<%@ Page Language="C#" AutoEventWireup="true"
    CodeFile="FileUpload.aspx.cs" Inherits="uploader_FileUpload"
    EnableSessionState="ReadOnly" %>

调用 Uploader 的 Save 方法

在保存页面的 Page_Load 方法中, 调用 Uploader 控件的 Save静态方法来保存文件:

protected void Page_Load ( object sender, EventArgs e )
{

    if ( this.IsPostBack && this.file.HasFile )
        // TODO: 这里设置 waitSecond 参数是为了在测试时显示上传的进度,
        // 在实际的使用中请不要设置 waitSecond, 并调整 bufferSize 为一个合理的值.
        Uploader.Save (
            this.Server.MapPath ( @"~/uploader/photo.jpg" ),
            this.file.PostedFile,
            this.Session["myphotouploadinfo"] as Uploader.UploadInfo,
            1,
            1 );
        //    Uploader.Save (
        //        this.Server.MapPath ( @"~/uploader/photo.jpg" ),
        //        this.file.PostedFile,
        //        this.Session["myphotouploadinfo"] as Uploader.UploadInfo );

}

代码中, 通过 IsPostBackHasFile 属性判断在用户提交了文件后, 才进行保存.

Save 方法的格式为 Save ( string filePath, HttpPostedFile postedFile, Uploader.UploadInfo uploadInfo, int bufferSize, int waitSecond ), filePath 参数是文件保存的完整路径, postedFile 参数是提供文件控制的 HttpPostedFile 对象, 可以从 FileUpload 控件获取, uploadInfo 参数是保存上传进度信息的对象, bufferSize 参数是保存文件时的缓存大小, 默认 128kb 保存一次, 最后一个参数 waitSecond 只在测试时使用, 表示缓存被保存后的等待时间, 这样可以确保看到进度.

上传大于 4mb 的文件, 请修改 web.config 的 maxRequestLength, 可以参考 http://msdn.microsoft.com/zh-cn/library/e1f13641(v=vs.71).aspx.

创建获取进度的页面

包含进度信息的对象 Uploader.UploadInfo 被保存在 Session 中, 因此可以随时从 Session中获取进度信息:

<%@ WebHandler Language="C#" Class="uploader_getprec" %>

using System.Collections.Generic;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.SessionState;
using zoyobar.shared.panzer.ui.jqueryui.plusin;

public class uploader_getprec : IHttpHandler,
    IReadOnlySessionState
{

    public void ProcessRequest ( HttpContext context )
    {
        context.Response.ContentType = "text/javascript";
        context.Response.Cache.SetNoStore ( );

        Uploader.UploadInfo info =
            context.Session["myphotouploadinfo"] as Uploader.UploadInfo;

        SortedDictionary<string, object> json =
            new SortedDictionary<string, object> ( );

        if ( null == info )
            json.Add ( "prec", "-" );
        else
        {
            json.Add ( "prec", info.Percent );
            json.Add ( "total", info.ContentLength );
            json.Add ( "posted", info.PostedLength );

            if ( info.Percent == 100 )
                json.Add ( "url", "photo.jpg" );

            /*
             * {
             *    "prec": 20.23
             *    "total": 2000,
             *    "posted": 2
             * }
             * */
        }

        context.Response.Write (
            new JavaScriptSerializer ( ).Serialize ( json )
            );
    }

    ...

}

需要注意的是, uploader_getprec 实现了接口 IReadOnlySessionState, 而不是 IRequiresSessionState. 原因也是和设置 EnableSessionState 为 ReadOnly 类似的. 至于如何返回 JSON 数据, 请参考 在不同的 .NET 版本中返回 JSON.

创建上传页面

最后一步就是创建一个上传页面, 在页面中添加 Uploader控件:

<je:Uploader ID="uploader" runat="server" IsVariable="true"
    UploadUrl="FileUpload.aspx"
    ProgressUrl="getprec.ashx" ProgressChanged="
function(data){

    if(-:data.prec == '-')
        $('#prec').text('没有进度!');
    else
        if(-:data.prec == 100){
            $('#prec').text('完成, 图片路径为: ' + -:data.url);

            pb.hide();

            $('#photo').show().attr('src', -:data.url);
        }
        else{
            $('#prec').text(-:data.posted +
                ' bytes/' + -:data.total + ' bytes, ' +
                -:data.prec + '%');
            pb.progressbar('option', 'value', -:data.prec);
        }

}
">
</je:Uploader>
<je:Button ID="cmdUpload" runat="server" IsVariable="true"
    Label="开始" Click="
function(){
    cmdUpload.hide();
    uploader.__uploader('hide').__uploader('upload');

    pb.show();
}">
</je:Button>

设置保存页面

通过 UploaderUploadUrl 属性, 可以选择保存页面, 示例中, 选择了页面 FileUpload.aspx, 这将自动生成一个 iframe 元素, iframe 的 src 属性指向 FileUpload.aspx 页面.

也可以自定义一个 iframe, 然后通过 Upload属性选择此 iframe:

<iframe id="myIFrame" src="FileUpload.aspx"></iframe>

<je:Uploader ID="uploader" runat="server" IsVariable="true"
    Upload="#myIFrame"
    ...    >
</je:Uploader>

设置获取进度的页面

通过属性 ProgressUrlProgressChanged 可以获取并显示上传进度, ProgressUrl 表示返回进度信息的页面地址, ProgressChanged 则用于处理返回的进度等信息.

此外 ProgressInterval 属性表示查询进度的时间间隔, 默认为 1000 毫秒.

上传

调用 uploaderupload方法, 即可触发上传操作:

<je:Button ID="cmdUpload" runat="server" IsVariable="true"
    Label="开始" Click="
function(){
    uploader.__uploader('upload');
}">
</je:Button>

默认情况下将对保存页面的第一个表单执行 submit 操作, 可以通过 UploadForm 属性来调整需要提交的表单的索引.

隐藏保存页面

调用 uploaderhide方法, 即可隐藏保存页面:

...
    uploader.__uploader('upload');
...

JQueryElement 是开源共享的代码, 可以在 http://code.google.com/p/zsharedcode/wiki/Download 页面下载 dll 或者是源代码.

实际过程演示: http://www.tudou.com/programs/view/-Zvwz5xsih8/, 建议全屏观看.

欢 迎访问 panzer 开源项目, http://zsharedcode.googlecode.com/ , 其中包含了 IEBrowser 控制 WebBrowser 执行各种 js 和 jQuery 脚本以及录制功能 和 jQueryUI 的 ASP.NET 控件 JQueryElement, 微博: http://t.qq.com/zoyobar

[转载]分享35款超酷的免费英文涂鸦字体

mikel阅读(1477)

[转载]分享35款超酷的免费英文涂鸦字体 – 梦想天空(山边小溪) – 博客园.

在街头艺术中,涂鸦是艺术家自我表达的常用形式。如今,在专业设计师的帮助下,我们也能够把涂鸦字体应用到我们的设计中,让我们的作品脱颖而 出。今天这篇文章就向大家分享35款超酷的免费英文涂鸦字体,如果您正在寻找漂亮的免费英文涂鸦字体,那么这份清单正是为您准备的,赶紧下载吧。

Malice

Free-Graffiti-Fonts-27

Urban Jungle

Free-Graffiti-Fonts-23

Sick Capital Vice

Free-Graffiti-Fonts-28

a dripping marker font

Free-Graffiti-Fonts-29

El&Font Urban CalIigraphy

Free-Graffiti-Fonts-24

DJ GROSS

Free-Graffiti-Fonts-25

Inner City

Free-Graffiti-Fonts-26

Ruthless One

Free-Graffiti-Fonts-01

Graffogie

Free-Graffiti-Fonts-02

ReskaGraf

Free-Graffiti-Fonts-03

Most Wasted

Free-Graffiti-Fonts-04

Subway

Free-Graffiti-Fonts-05

Sadoc Wild

Free-Graffiti-Fonts-06

QUB font

Free-Graffiti-Fonts-07

Servin’ For Salute

Free-Graffiti-Fonts-08

The Battle Continuez

Free-Graffiti-Fonts-09

JustFist

Free-Graffiti-Fonts-10

Bring Tha Noize

Free-Graffiti-Fonts-11

Writers

Free-Graffiti-Fonts-12

Aaaiight!

Free-Graffiti-Fonts-13

Broken Records (Font)

Free-Graffiti-Fonts-14

FAVELA free font

Free-Graffiti-Fonts-15

Antechamber (Free Typeface)

Free-Graffiti-Fonts-16

Laks Oner

Free-Graffiti-Fonts-17

Free Fonts

Free-Graffiti-Fonts-18

Brock Vandalo

Free-Graffiti-Fonts-19

Ruthless Two

Free-Graffiti-Fonts-20

blob – Free font by Superfried

Free-Graffiti-Fonts-21

梦想天空博客关注前端开发,展示最新HTML5CSS3应用,推荐优秀网页设计案例。

Progressive Fonts (free!)

Free-Graffiti-Fonts-22

Whoa!

Free-Graffiti-Fonts-31

Searfont

Free-Graffiti-Fonts-32

Street Soul

Free-Graffiti-Fonts-33

Souper 3

Free-Graffiti-Fonts-34

Scrawl 3rd

Free-Graffiti-Fonts-35

Let Me Ride font

Free-Graffiti-Fonts-30

[转载]五段实用的JavaScript淫荡技巧

mikel阅读(1030)

[转载]五段实用的js淫荡技巧 – !nothing – 博客园.

技巧一之setTimeout.


应用案例:比如你想一个函数循环执行10次,怎么办?以前通常是先setInterval,然后clearInterval,技巧一就是克服这个问题

(function () {
    var i = 0;
    function job() {
        console.log(i++);
        if (i < 10) {
            setTimeout(job, 1000);
        }
    }
    job();
    
})();

上面这个job函数就只会乖乖的执行10次.然后自动停止

技巧二之高效的for循环

应用案例:抛弃传统的循环方式

(function () {
   var arr=[];
   for(var i=arr.length;i--;){
      doStuff();
   }
})();

这个方式为什么高效?

一:少了一个参数l=arr.length;

二:for语句中间那个玩意少进行了一次计算,以前的话是for(i=0;i<l;i++)这样的话中间的语句会先比较i<l  然后比较出来的结果在

跟true 或者false比较,自然多了次计算

技巧三之高效赋值

应用案例:抛弃传统的if判断赋值

 var i=1,ret;
  ret=i!==1||true;
  console.log(ret);

以上代码会很神奇的告诉你ret会是true.高效吧不用if(i!==1)了在赋值了

技巧四之强悍的简短的attr

应用案例:setAttribute,getAttribute.这个方法不仅可以设置标准的属性,还可以设置任意属性,兼容好

function attr(elem, name, value) {
    var ret;
    if (value) {
        if (/msie [6-7]\.0/i.test(navigator.userAgent)) {
            ret = elem.getAttributeNode(name);
            if (!ret) {   //ie6 7不合法的属性设置捕鸟,通过这里可以设置
                ret = document.createAttribute(name);
                elem.setAttributeNode(ret);
            }
            ret.nodeValue = value + "";
        } else {
            elem.setAttribute(name, value);
        }
        return elem;
    } else {  //ie6 7有得属性获取不鸟
        ret = elem.getAttribute(name);
        fixIe = elem.getAttributeNode(name).nodeValue;
        ret = ret ? ret : fixIe ? fixIe : undefined;
        return ret;
    }
}

以上方法如何测试呢?

attr(document.getElementById(“test”), “classxx”, “xx”)
alert(attr(document.getElementById(“test”),”classxx”));

技巧五之getElementsByClassName.

应用案例 :以前js没什么框架的时候,大家都再模仿这个方法,看看今天我是怎么高效的模仿出它来.这也不愧是js初学者的经典代码

(function () {
   var getElementsByClassName=function(cls,context){
      var root = context || document;
    return document.querySelectorAll ? root.querySelectorAll("." + cls) : root.getElementsByClassName ?
           root.getElementsByClassName(cls) : help("*", cls, context);
   }
   var help=function(tagName,cls,context){
        var root= context || document,
            ret=[],elems,i,
            rcls=new RegExp("^|\\s+"+cls+"\\s+|$");
        elems = root.getElementsByTagName(tagName || "*");
        for(i=elems.length;i--;){
            if(rcls.test(elem[i].className)){
              ret.push(elems[i]);
            }
        }
        return ret;
   }
})();

以上几个js淫荡技巧还是蛮实用的,前提是你没用使用别人的js框架,用原生创造效率为前提的代码.

[转载]Android实现类似QQ列表

mikel阅读(1447)

[转载]【Android】实现类似QQ列表 – 朱红的泪 – 博客园.

感谢豆子兄弟的指点 . 本文是参照他的代码在经过一点改造 .

豆子的灵感是来自于 Google 的 Contacts( 联系人 ) 的实现 , 其中有一个类叫做 PinnedHeaderListView( 固定头的列表),本文也不做过多的解释,因为Google的程序中已经写得很清楚了.

本列表是根据自己需要专门实现类似于QQ列表的功能,所以可能扩展性不是很强,自己满足就好.

QQ: 列表显示效果

/**

* QQ 列表

* @author 朱红的泪 (V5)

*

*/

public class QQListView extends ExpandableListView implements OnScrollListener,

OnGroupClickListener {

public QQListView(Context context, AttributeSet attrs, int defStyle) {

super (context, attrs, defStyle);

registerListener();

}

public QQListView(Context context, AttributeSet attrs) {

super (context, attrs);

registerListener();

}

public QQListView(Context context) {

super (context);

registerListener();

}

/**

* Adapter 接口 . 列表必须实现此接口 .

*/

public interface QQHeaderAdapter {

public static final int PINNED_HEADER_GONE = 0;

public static final int PINNED_HEADER_VISIBLE = 1;

public static final int PINNED_HEADER_PUSHED_UP = 2;

/**

* 获取 Header 的状态

*

* @param groupPosition

* @param childPosition

* @return

*        PINNED_HEADER_GONE,PINNED_HEADER_VISIBLE,PINNED_HEADER_PUSHED_UP 其中之一

*/

int getQQHeaderState( int groupPosition, int childPosition);

/**

* 配置 QQHeader, 让 QQHeader 知道显示的内容

*

* @param header

* @param groupPosition

* @param childPosition

* @param alpha

*/

void configureQQHeader(View header, int groupPosition,

int childPosition, int alpha);

/**

* 设置组按下的状态 .

*

* @param groupPosition

* @param status

*/

void setGroupClickStatus( int groupPosition, int status);

/**

* 获取组按下的状态

*

* @param groupPosition

* @return

*/

int getGroupClickStatus( int groupPosition);

}

private static final int MAX_ALPHA = 255;

private QQHeaderAdapter mAdapter ;

/**

* 用于在列表头显示的 View,mHeaderViewVisible 为 true 才可见

*/

private View mHeaderView ;

/**

* 列表头是否可见

*/

private boolean mHeaderViewVisible ;

private int mHeaderViewWidth ;

private int mHeaderViewHeight ;

public void setHeaderView(View view, float height) {

mHeaderView = view;

AbsListView.LayoutParams lp = new AbsListView.LayoutParams(

ViewGroup.LayoutParams. MATCH_PARENT , ( int ) height);

view.setLayoutParams(lp);

if ( mHeaderView != null ) {

setFadingEdgeLength(0);

}

requestLayout();

}

private void registerListener() {

setOnScrollListener( this );

setOnGroupClickListener( this );

}

/**

* 点击 HeaderView 触发的事件

*/

private void headerViewClick() {

long packedPosition = getExpandableListPosition( this

.getFirstVisiblePosition());

int groupPosition = ExpandableListView

.getPackedPositionGroup(packedPosition);

if ( mAdapter .getGroupClickStatus(groupPosition) == 1) {

this .collapseGroup(groupPosition);

mAdapter .setGroupClickStatus(groupPosition, 0);

// 没设置这个会出现一些奇怪的问题 , 暂时不知道为什么

this .setSelectedGroup(groupPosition);

}

}

private float mDownX ;

private float mDownY ;

/**

* 如果 HeaderView 是可见的 , 此函数用于判断是否点击了 HeaderView, 并对做相应的处理 ,

* 因为 HeaderView 是画上去的 , 所以设置事件监听是无效的 , 只有自行控制 .

*/

@Override

public boolean onTouchEvent(MotionEvent ev) {

if ( mHeaderViewVisible ) {

switch (ev.getAction()) {

case MotionEvent. ACTION_DOWN :

mDownX = ev.getX();

mDownY = ev.getY();

if ( mDownX <= mHeaderViewWidth && mDownY <= mHeaderViewHeight ) {

return true ;

}

break ;

case MotionEvent. ACTION_UP :

float x = ev.getX();

float y = ev.getY();

float offsetX = Math.abs(x – mDownX );

float offsetY = Math.abs(y – mDownY );

// 如果 HeaderView 是可见的 , 点击在 HeaderView 内 , 那么触发 headerClick()

if (x <= mHeaderViewWidth && y <= mHeaderViewHeight

&& offsetX <= mHeaderViewWidth

&& offsetY <= mHeaderViewHeight ) {

if ( mHeaderView != null ) {

headerViewClick();

}

return true ;

}

break ;

default :

break ;

}

}

return super .onTouchEvent(ev);

}

@Override

public void setAdapter(ExpandableListAdapter adapter) {

super .setAdapter(adapter);

mAdapter = (QQHeaderAdapter) adapter;

}

/**

* 点击了 Group 触发的事件 , 要根据根据当前点击 Group 的状态来

*/

@Override

public boolean onGroupClick(ExpandableListView parent, View v,

int groupPosition, long id) {

if ( mAdapter .getGroupClickStatus(groupPosition) == 0) {

mAdapter .setGroupClickStatus(groupPosition, 1);

parent.expandGroup(groupPosition);

parent.setSelectedGroup(groupPosition);

} else if ( mAdapter .getGroupClickStatus(groupPosition) == 1) {

mAdapter .setGroupClickStatus(groupPosition, 0);

parent.collapseGroup(groupPosition);

}

// 返回 true 才可以弹回第一行 , 不知道为什么

return true ;

}

@Override

protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) {

super .onMeasure(widthMeasureSpec, heightMeasureSpec);

if ( mHeaderView != null ) {

measureChild( mHeaderView , widthMeasureSpec, heightMeasureSpec);

mHeaderViewWidth = mHeaderView .getMeasuredWidth();

mHeaderViewHeight = mHeaderView .getMeasuredHeight();

}

}

private int mOldState = -1;

@Override

protected void onLayout( boolean changed, int left, int top, int right,

int bottom) {

super .onLayout(changed, left, top, right, bottom);

final long flatPostion =getExpandableListPosition(getFirstVisiblePosition());

final int groupPos = ExpandableListView

.getPackedPositionGroup(flatPostion);

final int childPos = ExpandableListView

.getPackedPositionChild(flatPostion);

int state = mAdapter .getQQHeaderState(groupPos, childPos);

if ( mHeaderView != null && mAdapter != null && state != mOldState ) {

mOldState = state;

mHeaderView .layout(0, 0, mHeaderViewWidth , mHeaderViewHeight );

}

configureHeaderView(groupPos, childPos);

}

public void configureHeaderView( int groupPosition, int childPosition) {

if ( mHeaderView == null || mAdapter == null

|| ((ExpandableListAdapter) mAdapter ).getGroupCount() == 0) {

return ;

}

int state = mAdapter .getQQHeaderState(groupPosition, childPosition);

switch (state) {

case QQHeaderAdapter. PINNED_HEADER_GONE : {

mHeaderViewVisible = false ;

break ;

}

case QQHeaderAdapter. PINNED_HEADER_VISIBLE : {

mAdapter .configureQQHeader( mHeaderView , groupPosition,

childPosition, MAX_ALPHA );

if ( mHeaderView .getTop() != 0) {

mHeaderView .layout(0, 0, mHeaderViewWidth , mHeaderViewHeight );

}

mHeaderViewVisible = true ;

break ;

}

case QQHeaderAdapter. PINNED_HEADER_PUSHED_UP : {

View firstView = getChildAt(0);

int bottom = firstView.getBottom();

// intitemHeight = firstView.getHeight();

int headerHeight = mHeaderView .getHeight();

int y;

int alpha;

if (bottom < headerHeight) {

y = (bottom – headerHeight);

alpha = MAX_ALPHA * (headerHeight + y) / headerHeight;

} else {

y = 0;

alpha = MAX_ALPHA ;

}

mAdapter .configureQQHeader( mHeaderView , groupPosition,

childPosition, alpha);

if ( mHeaderView .getTop() != y) {

mHeaderView .layout(0, y, mHeaderViewWidth , mHeaderViewHeight

+ y);

}

mHeaderViewVisible = true ;

break ;

}

}

}

@Override

protected void dispatchDraw(Canvas canvas) {

super .dispatchDraw(canvas);

if ( mHeaderViewVisible ) {

drawChild(canvas, mHeaderView , getDrawingTime());

}

}

@Override

public void onScroll(AbsListView view, int firstVisibleItem,

int visibleItemCount, int totalItemCount) {

final long flatPos = getExpandableListPosition(firstVisibleItem);

int groupPosition = ExpandableListView.getPackedPositionGroup(flatPos);

int childPosition = ExpandableListView.getPackedPositionChild(flatPos);

configureHeaderView(groupPosition, childPosition);

}

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

}

}

邮箱:weiwutan@gmail.com

[转载]B2C电子商务系统研发——商品SKU分析和设计(一)

mikel阅读(1404)

[转载]B2C电子商务系统研发——商品SKU分析和设计(一) – 颜超敏 – 博客园.

一、SKU及相关概念定义

在设计商品SKU之前,首先让我们熟悉一下SKU和相关的一些概念。

# 什么是SKU:

SKU=Stock Keeping Unit(库存量单位)

同一型号的商品,或者说是同一个产品项目(商品条形码是针对企业的产品

项目来进行定义的),因为产品与产品之间有某些属性不同,用以区别开这些

不同商品的属性即商品变异属性,又称作SKU属性,因为它决定了SKU

的绝对数量。

# 参考说明

百度上有一篇文章也有阐述,可以做关联阅读,我就不重复贴上了。

http://www.cnblogs.com/winstonyan/admin/EditPosts.aspx

# 什么是SKU属性和选项

比如某件衣服有多种颜色、多种尺码,这些属性会直接关联价格和库存的,

系统会根据该商品关联的SKU属性的某个组合生成SKU。

比如某个款式的衬衫,有XL/L/XXL三种大小,有红黄蓝三种颜色。

对应这里例子,尺码和颜色都是是SKU属性。

对应尺码的XL/L/XXL等,都是SKU属性选项。

【注】上述的属性不一定在任何时候都是SKU属性,看实际的商品情况和设置。

比如对于尺码,某种商品是均码的。那么就不需要创建尺码这个SKU属性了,

而是设置为普通属性,仅作为显示用。

# 什么是商品SKU

商品SKU实际上就是SKU,为了避免误解和SKU属性混淆,我用商品SKU来命名,

表示从属于商品的、实际销售和存储的子实体。

一个商品SKU,表示该商品关联的若干SKU属性的的属性值的某个组合所形成的

子实体。

如对应上面的例子,其中的一种组合 XL + 红色 就会形成一个商品SKU。然后,

我们可以在该实体上管理价格、库存、专门的图片等信息。

# 什么是商品变异

英文名:Product Variants

商品变异其实就是商品SKU,只不过在某些技术文章中这样定义了。即以“变异”

来表达商品SKU的生成。

# 属性集

B2C电子商务系统研发——商品SKU分析和设计(一)

Attribute Set,用于管理各类扩展属性的集合,其中SKU属性也是在管理范畴之内。

商品通过关联属性集而获得该属性集设置好的SKU属性,然后才可以根据这些SKU属性

生成商品SKU。

属性集也成为产品类型。

常见的属性集有:服装、PC、家具、图书等。

# 概念的统一

虽然不同的研究人员有不同的命名和定义,但为了在本系列文章中不出现混淆,

我对概念做了以下统一定义:

1)SKU(或称商品SKU)指的是商品子实体。

2)商品和商品SKU是主次关系,一个商品包含若干个商品SKU子实体,商品SKU从属于商品。

3)SKU不是编码,每个SKU包含一个唯一编码,即SKU Code,用于管理。

4)商品本身也有一个编码,即Product Code,但不作为直接库存管理使用。
有时为了方便管理,会通过商品的Product Code作为前缀生成SKU Code。

二、SKU属性的管理

常见有几种情况:

  1. 商品独立管理
    即SKU属性从属于商品。
    优点:基本上没有。
    缺点:这种比较不靠谱,因为会导致工作量过大。虽然可以通过“复制”功能来稍稍
    简化,但依然不会很理想。所以基本不会采用。
  2. 商品独立关联
    即SKU属性是公共的,每个商品根据自己的实际情况来关联若干个SKU属性,
    然后选择若干选项生成商品SKU。
    优点:灵活,设置好了若干SKU属性和相关选项后,由商品自行选择相关的组合。
    缺点:太灵活了,容易出错。比如对于颜色这个SKU属性而言,由于是公共的,所以
    会定义数十个,甚至更多,但是对于ipad而言,其实只需要2个即可。这种
    管理方式,无法从源头控制商品添加时SKU属性和选项的范围。
  3. 通过属性集管理
    即SKU属性依附属性集存在,不存在可以从属于多个属性集的SKU属性。
    优点:容易进行严格的管理,不易出错。比如同样是命名为“颜色”的SKU属性会存在多个
    (属性ID/编码不同),但是对于ipad的只需要2个选项(黑、白),对于服装则会很多。
    缺点:属性集管理的工作量会稍大,适合属性集不多的系统。
  4. 通过属性集关联
    即SKU属性是公共的,通过属性集关联。
    优点:这种方式重用性不错,对于SKU选项较多的,会简化工作量。
    缺点:由于SKU属性是公共的,所以会存在上面第2点的缺点。但我们也可以通过设置多个
    同名、但编码不同的SKU属性,如多个“颜色”SKU属性,但是选项不同。
  5. 创建独立的SKU属性集
    即设计一个独立的SKU属性集的实体,关联或者直接管理SKU属性。
    这种方式也是挺不错的。因为虽然各种商品类型之间产品特性会有较大的不同,但是SKU属性
    却有可能差异不大。比如对于服装、ipad都存在通过颜色来区分SKU,但是ipad只需要2种选项
    (以后也许微调为3~4种等),而服装则很多了。

三、我的选择

上面介绍了五种形式,我个人倾向第4和第5种,上一篇文章的ER图也改成了第4种的形式,比较符合

常见的思路。第5种也是不错的。可以在接下来的设计分析一下。

[转载]Node.js 的安装和控制台命令

mikel阅读(972)

[转载]Node.js 的安装和控制台命令 – 坐看云起 – 博客园.

一、Node.js简介

为了说服您阅读这份简单的说明,我想先给Node.js做点广告还是有必要的。先看看都有谁在用Node.js吧,跟着业界老大混,总是大差不差的。首 先,微软的云服务Azure已经开始支持Node.js、还有就是Ebay、Yahoo、Linkedin,是不是有点精神了?嗯,我们继续。下面是官网的自我介绍:


Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

Node.js 是一个平台,建立在 Chrome JavaScript 运行时之上,目的是建立快速、可伸缩的网络应用。Node.js使用事件驱动,非阻塞的 I/O 模式,这使得他是轻量而高效的,能够在分布设备上完美运行高数据吞吐的实时应用。


如果官网没有王婆卖瓜的话,我想您应该有兴趣花上五分钟浏览下面的内容了。

二、安装

这里仅说明Windows平台安装,很简单,去官网下载安装包,运行,OK。

安装完毕后,也许您习惯的去找快捷方式。不好意思,虽然您眼神比我好,可是也是找不到滴。别着急,安装包默认把所有文件拷贝到了 “C:\Program Files\nodejs”目录下,然后,很体贴地设置好了系统环境变量里的path,现在,请打开一个命令行窗口,输入:

>node

>

如果你得到一个提示符,系统没警告说“对不起,没有此命令”,那么,恭喜,安装成功完成。如果你还想观察下nodejs的目录结构的话,也会发现超级简单,就是一个node.exe文件,还有比这更简单的吗?

啊?您说还有一个 npm.cmd 批处理文件和 node_modules 文件夹?那个,那个我们目前可以暂时无视。您可以删了他们而不影响 node.js 的使用。

不过既然提到他们,npm 是用来管理模块的,而 node.js 的魅力也在于他的模块化,内核只做内核该做的事,其他的一切,全通过模块的扩展来实现。这也为 node.js 带来了无尽可能。

可爱的模块们,一般就窝在 node_modules 文件夹里。

三、控制台命令和REPL

好了,既然我们得到了 node.js 的提示符,也就是说我们现在是在 node.js 的环境里了。在这个环境里,您所有的 Javascript 知识都可以派上用场了,因为 node.js 使用的就是著名的 v8 引擎。补充说明一下,node.js 把这个称作Read-Eval-Print-Loop,就是说,咱们在这里就可以交互地跑 js 代码了。感觉回到了最初学 Basic 的年代啊。怀念、怀念。

> a = [ 1, 2, 3]; 
[ 1, 2, 3
> a.forEach(function (v) {
 ... console.log(v);
... });
 1
 2
 3
为数不多的几个控制台命令可以用 help 查到,唯一需要注意的就是别忘了这些命令前面需要带上一个小圆点:
noderepl

好了,现在可以开始您的 node.js 之旅了,当然,如果你愿意的话。

[转载]使用JS获取FCKEditor中的内容

mikel阅读(1052)

[转载]使用JS获取FCKEditor中的内容 .

  1. / 获取FCKEditor中的内容: content为Editor实例的ID
  2. function getEditorContents(){
  3. var oEditor = FCKeditorAPI.GetInstance(“content”);
  4. alert(oEditor.GetXHTML(true));
  5. }
  6. // 向编辑器插入指定代码
  7. function insertHTMLToEditor(codeStr){
  8. var oEditor = FCKeditorAPI.GetInstance(“content”);
  9. if (oEditor.EditMode==FCK_EDITMODE_WYSIWYG){
  10. oEditor.InsertHtml(codeStr);
  11. }else{
  12. return false;
  13. }
  14. }
  15. // 统计编辑器中内容的字数
  16. function getLength(){
  17. var oEditor = FCKeditorAPI.GetInstance(“content”);
  18. var oDOM = oEditor.EditorDocument;
  19. var iLength ;
  20. if(document.all){
  21. iLength = oDOM.body.innerText.length;
  22. }else{
  23. var r = oDOM.createRange();
  24. r.selectNodeContents(oDOM.body);
  25. iLength = r.toString().length;
  26. }
  27. alert(iLength);
  28. }
  29. // 执行指定动作
  30. function ExecuteCommand(commandName){
  31. var oEditor = FCKeditorAPI.GetInstance(“content”) ;
  32. oEditor.Commands.GetCommand(commandName).Execute() ;
  33. }
  34. // 设置编辑器中内容
  35. function SetContents(codeStr){
  36. var oEditor = FCKeditorAPI.GetInstance(“content”) ;
  37. oEditor.SetHTML(codeStr) ;
  38. }
作者: Sjolzy

[转载]ASP.NET MVC 3 开发的20个秘诀(十二)[20 Recipes for Programming MVC 3]:缩放图片尺寸创建缩略图

mikel阅读(775)

[转载][翻译]ASP.NET MVC 3 开发的20个秘诀(十二)[20 Recipes for Programming MVC 3]:缩放图片尺寸创建缩略图 – O2DS – 博客园.

议题

用户上传到网站上的大多数的图片都是大尺寸的照片,通常在用户想看完整图片之前网站会展示出这些图片或照片的缩略图。

解决方案

使用以下的类来调整上传的图片文件的宽和高:FileStream,Image,Bitmap和Graphics。

讨论

在下面的示例中,将修改和重组之前创建的FileUpload类。创建一个新的称为“ResizeImage”的方法来调整图片大小。调整之后的图 片文件将被保存到源文件存储文件夹的子文件夹“Thumbnails”中。同时也要修改DeleteFile方法,添加同时删除原始图像和缩略图,并且为 了避免重复代码要创建一个新的删除功能的方法。下面显示变化部分的类代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace MvcApplication4.Utils
{
    public static class FileUpload
    {
        public static char DirSeparator =
        System.IO.Path.DirectorySeparatorChar;
        public static string FilesPath = "Content" +
        DirSeparator + "Uploads" + DirSeparator;
        public static string UploadFile(HttpPostedFileBase file)
        {
            ...
            // 保存缩略图
            ResizeImage(file, 150, 100);
            ...
        }
        public static void DeleteFile(string fileName)
        {
            // 如果没有指定文件名就什么都不做
            if (fileName.Length == 0) return;
            // 设置删除路径
            string path = FilesPath + DirSeparator + fileName;
            string thumbPath = FilesPath + DirSeparator +
            "Thumbnails" + DirSeparator + fileName;
            RemoveFile(path);
            RemoveFile(thumbPath);
        }
        private static void RemoveFile(string path)
        {
            // 检查文件是否存在
            if (File.Exists(Path.GetFullPath(path)))
            {
                // 删除文件
                File.Delete(Path.GetFullPath(path));
            }
        }
        public static void ResizeImage(HttpPostedFileBase file,
        int width, int height)
        {
            string thumbnailDirectory =
            String.Format(@"{0}{1}{2}", FilesPath,
            DirSeparator, "Thumbnails");
            // 检查目标文件夹是否存在
            if (!Directory.Exists(thumbnailDirectory))
            {
                // 假如文件夹不存在就创建它
                Directory.CreateDirectory(thumbnailDirectory);
            }
            // 设置缩略图保存路径
            string imagePath =
            String.Format(@"{0}{1}{2}", thumbnailDirectory,
            DirSeparator, file.FileName);
            // 将文件流保存到磁盘
            FileStream stream = new FileStream(Path.GetFullPath(
            imagePath), FileMode.OpenOrCreate);
            // 缩放上传的文件
            Image OrigImage = Image.FromStream(file.InputStream);
            // 创建缩略图对象
            Bitmap TempBitmap = new Bitmap(width, height);
            // 创建缩略图画质
            Graphics NewImage = Graphics.FromImage(TempBitmap);
            NewImage.CompositingQuality =
            CompositingQuality.HighQuality;
            NewImage.SmoothingMode =
            SmoothingMode.HighQuality;
            NewImage.InterpolationMode =
            InterpolationMode.HighQualityBicubic;
            // 创建Rectangle对象进行绘制
            Rectangle imageRectangle = new Rectangle(0, 0,
            width, height);
            NewImage.DrawImage(OrigImage, imageRectangle);
            // 保存缩略图
            TempBitmap.Save(stream, OrigImage.RawFormat);
            // 释放资源
            NewImage.Dispose();
            TempBitmap.Dispose();
            OrigImage.Dispose();
            stream.Close();
            stream.Dispose();
        }
    }
}

在上面的示例中,我们做了许多修改,特别创建ResizeImage方法。首先,判断“Thumbnails”文件夹是否存在以及创建功能。接下来,会创建一个新的FileStream对象,并将编辑后的图片保存到“Thumbnails”文件夹中。

从提交的InputStream创建原始图片对象。然后基于缩略图的尺寸创建缩略图的Bitmap位图实例。然后基于这个Bitmap对象创建新的 Graphics对象,然后设置图像的画质、平滑度、插值模式,如果不设置这些值,缩略图会因为很像素化和比例变形变的很难看。

将这些值都设置完毕,创建一个原始尺寸的Recangle对象,将这个对象缩放后绘制到之前创建的Graphics对象中,这时才实际调整尺寸。最后保存Bitmap对象,释放所有资源。

参考

FileStream Image Bitmap Graphics 原书地址 书籍源代码

[转载]c# 扩展方法奇思妙用基础篇八:Distinct 扩展

mikel阅读(913)

[转载]c# 扩展方法奇思妙用基础篇八:Distinct 扩展 – 鹤冲天 – 博客园.

刚看了篇文章 《Linq的Distinct太不给力了》,文中给出了一个解决办法,略显复杂。

试想如果能写成下面的样子,是不是更简单优雅:

1
2
var p1 = products.Distinct(p => p.ID);
var p2 = products.Distinct(p => p.Name);

使用一个简单的 lambda 作为参数,也符合 Linq 一贯的风格。

可通过扩展方法 实现:

Distinct 扩展方法

首先,创建一个通用比较的类,实现 IEqualityComparer<T> 接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Linq;

public class CommonEqualityComparer<T, V> : IEqualityComparer<T>
{
    private Func<T, V> keySelector;

    public CommonEqualityComparer(Func<T, V> keySelector)
    {
        this.keySelector = keySelector;
    }

    public bool Equals(T x, T y)
    {
        return EqualityComparer<V>.Default.Equals(keySelector(x), keySelector(y));
    }

    public int GetHashCode(T obj)
    {
        return EqualityComparer<V>.Default.GetHashCode(keySelector(obj));
    }
}

第 17 行,用到了 EqualityComparer<T> 类,本文最后有简要说明

借助上面这个类,Distinct 扩展方法就很好写了:

1
2
3
4
5
6
7
public static class DistinctExtensions
{
    public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector)
    {
        return source.Distinct(new CommonEqualityComparer<T, V>(keySelector));
    }
}

呵呵,简单吧!

Distinct 使用示例

根据 ID :

1
2
3
4
5
6
7
var data1 = new Person[] {
    new Person{ ID = 1, Name = "鹤冲天"},
    new Person{ ID = 1, Name = "ldp"}
};
var ps1 = data1
    .Distinct(p => p.ID)
    .ToArray();

根据 Name:

1
2
3
4
5
7
var data2 = new Person[] {
    new Person{ ID = 1, Name = "鹤冲天"},
    new Person{ ID = 2, Name = "鹤冲天"}
};
var ps2 = data2
    .Distinct(p => p.Name)
    .ToArray();

看了回复后,我做了些改进,推荐使用下面的方式

改进

回复中有朋友提到“不区分大小写地排除重复的字符串”,也不难实现,只需要把上面的代码改进下就 OK:

CommonEqualityComparer<T, V> 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Linq;

public class CommonEqualityComparer<T, V> : IEqualityComparer<T>
{
    private Func<T, V> keySelector;
    private IEqualityComparer<V> comparer;

    public CommonEqualityComparer(Func<T, V> keySelector, IEqualityComparer<V> comparer)
    {
        this.keySelector = keySelector;
        this.comparer = comparer;
    }

    public CommonEqualityComparer(Func<T, V> keySelector)
        : this(keySelector, EqualityComparer<V>.Default)
    {  }

    public bool Equals(T x, T y)
    {
        return comparer.Equals(keySelector(x), keySelector(y));
    }

    public int GetHashCode(T obj)
    {
        return comparer.GetHashCode(keySelector(obj));
    }
}

Distinct 扩展方法

1
2
3
4
5
6
7
8
9
10
11
12
public static class DistinctExtensions
{
    public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector)
    {
        return source.Distinct(new CommonEqualityComparer<T, V>(keySelector));
    }

    public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector, IEqualityComparer<V> comparer)
    {
        return source.Distinct(new CommonEqualityComparer<T, V>(keySelector, comparer));
    }
}

借助可选参数,这两个扩展方法也可以合成一个:

1
2
3
4
5
public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector,
    IEqualityComparer<V> comparer = EqualityComparer<V>.Default)
{
    return source.Distinct(new CommonEqualityComparer<T, V>(keySelector, comparer));
}

(同样,CommonEqualityComparer<T, V>类的两个构造函数也可以合二为一)

使用示例:

1
2
3
4
5
6
7
var data3 = new Person[] {
    new Person{ ID = 1, Name = "LDP"},
    new Person{ ID = 2, Name = "ldp"}
};
var ps3 = data3
    .Distinct(p => p.Name, StringComparer.CurrentCultureIgnoreCase)
    .ToArray();

EqualityComparer<T> 类 简要说明

EqualityComparer<T>为 IEqualityComparer<T> 泛型接口的实现提供基类,它在 .net 4 中有五个重要的子类,见下图:image

这五个子类分别用不同类型数据的相等性比较,从类名我们可以略知一二。

这五个子类都是内部类(internal),不能直接访问,EqualityComparer<T> 类提供一个简单的属性 Default。EqualityComparer<T> 会根据传入的 T 的类型,加载不同的子类,并会予以缓存提高性能。

C#扩展方法奇思妙用》系统文章从 2009 年 08 月开始写起,到现在一共有了 22 篇,欢迎阅读:

基础篇: 中文处理string 常用扩展byte 常用扩展Random 扩展Dictionary<TKey, TValue> 扩展WhereIf 扩展IsBetween 通用扩展WhereIf 扩展Distinct 扩展
高级篇: 改进 Scottgu 的 “In” 扩展Aggregate扩展其改进Enumerable.Cast<T>应用对扩展进行分组管理ToString(string format) 扩展WinForm 控件选择器树”通用遍历器Type类扩展
变态篇: 由Fibonacci数列引出“委托扩展”及“递推递归委托”封装 if/else、swith/case及whileswitch/case 组扩展string 的翻身革命
性能篇 扩展方法性能初测
MVC篇: 巧用扩展方法优先级,美化所有页面TextBoxFor文本框

——————-