[转载]BlueStacks 安卓模拟器修改 IMEI | 螳螂虾

mikel阅读(1710)

[转载]BlueStacks 安卓模拟器修改 IMEI | 螳螂虾.

这个教程是某群友分享出来的,先说一声感谢你无私的分享。亲测有效,另外简单易懂操作,实乃居家旅行抢购秒杀必备教程。

至于用它可以做点什么,这里就要保密了。需要的时候自然时手到擒来。

IMEI 百科

这里我也在群友的分享之下,受益匪浅。有必要先记录一下,谨防以后遗漏。由于教程已经写很详细了,我就偷懒能复制的复制过来了。

准备工具:

Bluestacks 0.7.7.813 REL – 百度网盘

Root_20121221.rar – 百度网盘

GUID2IMEI.rar – 百度网盘

一键关闭Bluestacks.exe – 百度网盘

需要密码,输入 tanglangxia.com

bluestacks Bluestacks

步骤:

1、安装 BlueStacks 软件

2、解压 Root_20121221 和 Guid2IMEI,在 Root_20121221 里找到 Root.fs 文件,然后复制覆盖,文件路径如下:

  • win7 – C:\ProgramData\BlueStacks\Android
  • XP – C:\Documents and Settings\All Users\Application Data\BlueStacks\Android

这个文件夹内里的同名文件,注意首先要打开隐藏文件,否则该文件不可见。

3、覆盖之后准备工作完成

4、一键关闭所有 BS 进程(HD 开头一共6-7个),再打开软件 Guid2IMEI 并运行,首选读取注册表,然后生成 GUID 在生产 IMEI (两者顺序可以颠倒),生成完毕后写入注册表。(也可以简略快捷的生成  GUID 直接写入)

5、重启 BS

最后想说,分享无私,然后低调低调。

[转载]Android 双卡双待识别 - banketree - 博客频道 - CSDN.NET

mikel阅读(1140)

[转载]Android 双卡双待识别 – banketree – 博客频道 – CSDN.NET.

简介

Android双卡双待已经越来越普及了,解决双卡双待管理是广大手机开发人员必须得面对的问题,为实现Android平台的双卡双待操作,笔者研究了Android 应用层操作双卡双待的机制。

 

机制

获取基于ITelephony接口实现phone应用中的“phone服务”,通过TelephonyManager接口获取不同的卡(GSMPhone /CDMAPhone)进行不同的操作(拨号、接通、挂断、保持通话等)。

Android 平台是一个多样型的平台,不同的手机获取ITelephony接口不同,用一种方法实现双卡双待管理是不可取的。那怎么办呢?只有针对不同的手机分析出一 套管理的方案,该方案实现难度大,因为需要各个厂家的SDK的资料。为了实现该功能,笔者做了大量工作,整合各个厂家的SDK的资料。

 

实现

为了更好的管理双卡双待的问题,新建一个双卡双待模块静态库,其它项目引用便是,项目如图:

AbsSim是抽象类,负责实现手机操作的类。不同的厂家继承该类实现各自的接口。AbsSim信息如下:

public abstract class AbsSim implements IDualDetector { //抽象基类
protected final String TAG = getClass().getSimpleName();
protected ArrayList mSimSlots = new ArrayList();
protected boolean mIsDualSimPhone = false;
protected String mCallLogExtraField = "";

public abstract String getSimPhoneNumber(int paramInt); // 返回手机号码

public abstract int getDataState(int paramInt);// 返回数据状态

public abstract String getIMSI(int paramInt);// 返回手机标识

public abstract String getIMSI(int paramInt, Context paramContext);// 返回手机标识

public abstract int getPhoneState(int paramInt);// 返回手机状态

public abstract boolean isServiceAvaliable(int paramInt);// 服务是否可用

public abstract boolean isSimStateIsReady(int paramInt);// 卡是否在使用

public abstract int getSimOperator(int paramInt);// 服务商(电信、移动、联通)

protected abstract Object getITelephonyMSim(int paramInt);// 获取操作接口

protected abstract Object getMSimTelephonyManager(int paramInt);// 获取操作接口

@Override
public AbsSim detect() { // 根据手机信息匹配
if ((getITelephonyMSim(0) != null) && (getITelephonyMSim(1) != null)
// && (getmMSimSmsManager(0) != null)
// && (getmMSimSmsManager(1) != null)
// && (detectSms(paramContext, paramBoolean))
// && (detectCallLog(paramContext, paramBoolean))
)
return this;
return null;
}

public boolean directCall(String paramString, int paramInt) { // 拨打电话(根据不同卡拨打电话)
Intent localIntent = new Intent("android.intent.action.CALL",
Uri.fromParts("tel", paramString, null));
localIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
getContext().startActivity(localIntent);
return true;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
return false;
}

protected boolean detectCallLog() { // 通过通话记录信息匹配
return false;
}

protected boolean detectSms() {// 通过短信记录信息匹配
return false;
}

protected Context getContext() { // 返回句柄
return SimManager.getInstance().getContext();
}

protected int getSimSlotNum() { // 返回插槽个数(默认2)
return 2;
}

public void init() { // 初始化
for (int i = 0; i < getSimSlotNum(); i++) {
try {
String imsi = getIMSI(i);
boolean isUsing = isSimStateIsReady(i);
if (imsi != null || isUsing) {
if (imsi == null || hasSimSlotByIMSI(imsi))
continue;

SimSlot simSlot = new SimSlot();
mSimSlots.add(simSlot);
simSlot.setUsing(isUsing);
simSlot.setIMSI(imsi);
simSlot.setSimOperator(getSimOperator(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

public boolean hasSimPhone() {// 是否有sd卡在使用
if (mSimSlots.isEmpty())
return false;

for (SimSlot simslot : mSimSlots) {
if (simslot.isUsing())
return true;
}

return false;
}

public boolean isDualSimPhone() {// 是否为双卡
if (getSimSlots().isEmpty() || getSimSlots().size() < 2)
return false;

for (SimSlot simSlot : getSimSlots()) {
if (!simSlot.isUsing())
return false;
}

return true;
}

public ArrayList getSimSlots() { // 返回已确认的卡
return mSimSlots;
}

protected boolean delSimSlotByIMSI(String imsi) { // 删除相同的卡的信息
for (SimSlot simSlot : getSimSlots()) {
if (simSlot.getIMSI() != null && simSlot.getIMSI().equals(imsi)) {
getSimSlots().remove(simSlot);
}
}

return false;
}

protected boolean hasSimSlotByIMSI(String imsi) {
for (SimSlot simSlot : getSimSlots()) {
if (simSlot.getIMSI() != null && simSlot.getIMSI().equals(imsi)) {
return true;
}
}

return false;
}
}

现在列举一款实现MTK方案:

public class MTKDualSim extends AbsSim {// 采用MTK方案的类(根据厂家SDK实现不同的接口)
private Object mMSimTelephonyManager = null;
private Object mTelephonyMSim = null;

public MTKDualSim() {
mCallLogExtraField = "simid";

String str1 = SimManager.getModel();
String str2 = SimManager.getManufaturer();
if ((str1 != null) && (str2 != null)) {
String str3 = str1.toLowerCase();
String str4 = str2.toLowerCase();
if ((str4.indexOf("huawei") > -1) && (str3.indexOf("h30-t00") > -1))
mCallLogExtraField = "subscription";
if ((str4.indexOf("hisense") > -1)
&& (str3.indexOf("hs-u970") > -1)) {
mCallLogExtraField = "subtype";
}
}
}

@Override
public boolean directCall(String paramString, int paramInt) {
if (SimManager.isSDKVersionMore4_1()) {
Intent localIntent1 = new Intent("android.intent.action.CALL",
Uri.fromParts("tel", paramString, null));
localIntent1.putExtra("simId", paramInt);
localIntent1.putExtra("com.android.phone.extra.slot", paramInt);
localIntent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
getContext().startActivity(localIntent1);
return true;
} catch (Throwable localThrowable1) {
localThrowable1.printStackTrace();
}
} else if (SimManager.isSDKVersionMore4_0()) {
Intent localIntent2 = new Intent(
"com.android.phone.OutgoingCallReceiver");
localIntent2.putExtra("com.android.phone.extra.slot", paramInt);
localIntent2.putExtra("simId", paramInt);
localIntent2.putExtra("com.android.phone.force.slot", true);
localIntent2.setClassName("com.android.phone",
"com.android.phone.OutgoingCallReceiver");
localIntent2.setData(Uri.fromParts("tel", paramString, null));
try {
getContext().sendBroadcast(localIntent2);
return true;
} catch (Throwable localThrowable2) {
localThrowable2.printStackTrace();
}
}

try {
Intent localIntent3 = new Intent();
localIntent3.setAction("out_going_call_to_phone_app");
localIntent3.putExtra("number", paramString);
localIntent3.putExtra("simId", paramInt);
localIntent3.putExtra("com.android.phone.extra.slot", paramInt);
localIntent3.putExtra("launch_from_dialer", 1);
localIntent3.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().sendBroadcast(localIntent3);
return true;
} catch (Throwable localThrowable3) {
localThrowable3.printStackTrace();
}
return false;
}

@Override
public AbsSim detect() {
String imsi = getIMSI(0);
if (imsi != null && !TextUtils.isEmpty(imsi)) {
return this;
}

return super.detect();
}

@Override
public String getSimPhoneNumber(int paramInt) {
Object[] arrayOfObject2 = new Object[1];
try {
Object localObject = getMSimTelephonyManager(paramInt);
arrayOfObject2[0] = Integer.valueOf(paramInt);
String result = (String) ReflecterHelper.invokeMethod(localObject,
"getLine1NumberGemini", arrayOfObject2);
arrayOfObject2 = null;
return result;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
return "";
}

@Override
public int getDataState(int paramInt) {
Object[] arrayOfObject2 = new Object[1];
try {
Object localObject = getMSimTelephonyManager(paramInt);
arrayOfObject2[0] = Integer.valueOf(paramInt);
int result = ((Integer) ReflecterHelper.invokeMethod(localObject,
"getDataStateGemini", arrayOfObject2)).intValue();
arrayOfObject2 = null;
return result;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
arrayOfObject2 = null;
return -1;
}

@Override
public String getIMSI(int paramInt) {
return getIMSI(paramInt, null);
}

@Override
public String getIMSI(int paramInt, Context paramContext) {
Object localObject = getMSimTelephonyManager(paramInt);
Object[] arrayOfObject2 = new Object[1];
try {
arrayOfObject2[0] = Integer.valueOf(paramInt);
String result = (String) ReflecterHelper.invokeMethod(localObject,
"getSubscriberIdGemini", arrayOfObject2);
arrayOfObject2 = null;
return result;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
arrayOfObject2 = null;
return null;
}

@Override
public int getPhoneState(int paramInt) {
Object localObject = getMSimTelephonyManager(paramInt);
Object[] arrayOfObject2 = new Object[1];
try {
arrayOfObject2[0] = Integer.valueOf(paramInt);
int result = ((Integer) ReflecterHelper.invokeMethod(localObject,
"getCallStateGemini", arrayOfObject2)).intValue();
arrayOfObject2 = null;
return result;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
arrayOfObject2 = null;
return 0;
}

@Override
public boolean isServiceAvaliable(int paramInt) {
Object localObject = getITelephonyMSim(paramInt);
if (localObject == null)
return false;
Object[] arrayOfObject2 = new Object[1];
try {
arrayOfObject2[0] = Integer.valueOf(paramInt);
boolean result = ((Boolean) ReflecterHelper.invokeMethod(
localObject, "isRadioOnGemini", arrayOfObject2))
.booleanValue();
arrayOfObject2 = null;
return result;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
arrayOfObject2 = null;
return false;
}

@Override
public boolean isSimStateIsReady(int paramInt) {
Object localObject = getMSimTelephonyManager(paramInt);
if (localObject != null) {
Object[] arrayOfObject2 = new Object[1];
try {
arrayOfObject2[0] = Integer.valueOf(paramInt);
int result = ((Integer) ReflecterHelper.invokeMethod(
localObject, "getSimStateGemini", arrayOfObject2))
.intValue();
arrayOfObject2 = null;
return result == 5;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
arrayOfObject2 = null;
}

return false;
}

@Override
public int getSimOperator(int paramInt) { // 注意
Object localObject = getMSimTelephonyManager(paramInt);
Object[] arrayOfObject2 = new Object[1];
try {
arrayOfObject2[0] = Integer.valueOf(paramInt);
String result = ((String) ReflecterHelper.invokeMethod(localObject,
"getSimOperatorGemini", arrayOfObject2));
arrayOfObject2 = null;
return Integer.valueOf(result);
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
arrayOfObject2 = null;
return 0;
}

@Override
protected Object getITelephonyMSim(int paramInt) {
if (mTelephonyMSim == null)
mTelephonyMSim = ITelephony.Stub.asInterface(ServiceManager
.getService("phone"));
return mTelephonyMSim;
}

@Override
protected Object getMSimTelephonyManager(int paramInt) {
if (mMSimTelephonyManager != null)
return mMSimTelephonyManager;
Object[] arrayOfObject3 = new Object[1];
try {
mMSimTelephonyManager = SimManager.getInstance()
.getTelephonyManagerByPhone();
try {
Object localObject = mMSimTelephonyManager;
arrayOfObject3[0] = Integer.valueOf(0);
ReflecterHelper.invokeMethod(localObject,
"getSubscriberIdGemini", arrayOfObject3);
arrayOfObject3 = null;
return mMSimTelephonyManager;
} catch (Throwable localThrowable2) {
localThrowable2.printStackTrace();
}
} catch (Throwable localThrowable1) {
localThrowable1.printStackTrace();
}
arrayOfObject3 = null;
return null;
}
}

再列举一款单卡的方案:

public class SingleSim extends AbsSim implements IDualDetector {// 单卡方案
private final String TAG = getClass().getSimpleName();
private HashMap<String, Byte> mCallLogExtraFields = new SingleSim$1(this);

@Override
public boolean hasSimPhone() {
return false;
}

@Override
public AbsSim detect() {// 根据某些字段判是否为双卡(有可能误判)
if (mIsDualSimPhone)
return null;

Cursor localSafeCursor = null;
String[] arrayOfString;
try {
localSafeCursor = SimManager
.getInstance()
.getContext()
.getContentResolver()
.query(CallLog.Calls.CONTENT_URI, null, null, null,
"_id limit 0,1");

if (localSafeCursor != null && localSafeCursor.moveToFirst()) {
arrayOfString = localSafeCursor.getColumnNames();

for (int i = 0; i < arrayOfString.length; i++) {
String str = arrayOfString[i];
if (mCallLogExtraFields.containsKey(str.toLowerCase())) {
mIsDualSimPhone = true;
mCallLogExtraField = str;
}
}

}
} catch (Exception e) {
e.printStackTrace();
}

return this;
}

@Override
public boolean isDualSimPhone() {
return mIsDualSimPhone;
}

@Override
public int getSimSlotNum() {
return 1;
}

@Override
public String getSimPhoneNumber(int paramInt) {
return ((TelephonyManager) getMSimTelephonyManager(0)).getLine1Number();
}

@Override
public int getDataState(int paramInt) {
return ((TelephonyManager) getMSimTelephonyManager(0)).getDataState();
}

@Override
public String getIMSI(int paramInt) {
return ((TelephonyManager) getMSimTelephonyManager(0)).getDeviceId();
}

@Override
public String getIMSI(int paramInt, Context paramContext) {
return ((TelephonyManager) getMSimTelephonyManager(0))
.getSubscriberId();
}

@Override
public int getPhoneState(int paramInt) {
return ((TelephonyManager) getMSimTelephonyManager(0)).getCallState();
}

@Override
public boolean isServiceAvaliable(int paramInt) {
ITelephony localITelephony = (ITelephony) getITelephonyMSim(0);
if (localITelephony == null)
return false;
try {
boolean bool = localITelephony.isRadioOn();
return bool;
} catch (Throwable localThrowable) {
localThrowable.printStackTrace();
}
return false;
}

@Override
public boolean isSimStateIsReady(int paramInt) {
return ((TelephonyManager) getMSimTelephonyManager(0)).getSimState() == 5;
}

@Override
public int getSimOperator(int paramInt) {
TelephonyManager localTelephonyManager = (TelephonyManager) getMSimTelephonyManager(paramInt);
return Integer.parseInt(localTelephonyManager.getSimOperator());
}

@Override
protected Object getITelephonyMSim(int paramInt) {
return SimManager.getInstance().getITelephonyByPhone();
}

@Override
protected Object getMSimTelephonyManager(int paramInt) {
return SimManager.getInstance().getTelephonyManagerByPhone();
}
}
总结

利用java 反射机制操作Android隐藏的类,很好的解决了双卡双待的问题。
Java反射是 Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信 息,并可于运行时改变fields内容或唤起methods。

 

项目下载

[转载]Android类装载器DexClassLoader的简单使用-----制作android插件的前奏 - David小硕 - 博客园

mikel阅读(1197)

[转载]Android类装载器DexClassLoader的简单使用—–制作android插件的前奏 – David小硕 – 博客园.

声明:此篇文章借鉴《Android内核剖析》整理得来。

一、装载器简介

“类装载器”(ClassLoader),顾名思义,就是用来动态装载class文件的。标准的Java SDK中有个ClassLoader类,借助此类可以装载需要的class文件,前提是

ClassLoader类初始化必须制定class文件的路径。

import关键字引用的类文件和ClassLoader动态加载类的区别:

import引用类的两个特点:1、必须存在于本地,当程序运行该类时,内部类装载器会自动装载该类。

2、编译时必须在现场,否则编译过程会因找不到引用文件而不能正常编译。

classLoader的特点正好于import相反,而且更自由灵活。

每一个ClassLoader必须有一个父ClassLoader,在装载Class文件时,子ClassLoader会先请求其父 ClassLoader加载该文件,只有当其父ClassLoader找不到该文件时,子ClassLoader才会继承装载该类。这是一种安全机制。对 于Android而言,最终的apk文件包含的是dex类型的文件,dex文件是将class文件重新打包,打包的规则又不是简单地压缩,而是完全对 class文件内部的各种函数表,变量表进行优化,产生一个新的文件,即dex文件。因此加载这种特殊的Class文件就需要特殊的类加载器 DexClassLoader。

二、DexClassLoader的方法的实用

假设有两个apk,第一个叫做Host,第二个叫Plugin。Plugin中第一个一个类Plugin,该类中定义了一个addition函数。

package com.david.plugin;

import android.util.Log;

public class Plugin {

private static final String TAG=Plugin.class.getSimpleName();

public Plugin(){
Log.i(TAG, "PluginClass is initialized");
}

public int addition(int a,int b){
return a+b;
}

}

plugin的apk中AndroidManifest文件中,activity必须声明一个action。








将plugin.apk装载进Android设备中。Host.apk中主activity调用的代码如下:

package com.david.host;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import dalvik.system.DexClassLoader;
import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends ActionBarActivity implements OnClickListener{

private static final String plugin_package = "com.david.plugin.client";
private PackageManager pm;
private ResolveInfo resolveInfo;
private Button btn_classLoader;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// useDexClassLoader();
btn_classLoader=(Button) findViewById(R.id.btn_classLoader);
btn_classLoader.setOnClickListener(this);
}

@SuppressLint("NewApi")
public void useDexClassLoader() {
Intent classIntent = new Intent(plugin_package, null);
pm = getPackageManager();
List activities = pm.queryIntentActivities(classIntent, 0);
resolveInfo = activities.get(0);
ActivityInfo activityInfo = resolveInfo.activityInfo;

String div = System.getProperty("path.separator");
String packageName = activityInfo.packageName;
String sourceDir = activityInfo.applicationInfo.sourceDir;
System.out.println(sourceDir);
String outDir = getApplicationInfo().dataDir;
System.out.println(outDir);
String libraryDir = activityInfo.applicationInfo.nativeLibraryDir;
System.out.println(libraryDir);

DexClassLoader dexcl = new DexClassLoader(sourceDir, outDir,
libraryDir, this.getClass().getClassLoader());
try {
Class<?> loadClass = dexcl.loadClass(packageName+".Plugin");
Object instance = loadClass.newInstance();
Class[] params = new Class[2];
params[0]=Integer.TYPE;
params[1]=Integer.TYPE;
Method method = loadClass.getMethod("addition", params);
Integer result = (Integer) method.invoke(instance, 12,32);
System.out.println(result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

@Override
public void onClick(View v) {
useDexClassLoader();
}
}

 运行后得到的结果是:

 

类加载器在应用中还是用到比较多,还可以基于它设计一种“插件”架构。

[转载]ASP.NET WebForm中异步请求防止XSRF攻击的方法 - Nic Pei - 博客园

mikel阅读(1517)

[转载]ASP.NET WebForm中异步请求防止XSRF攻击的方法 – Nic Pei – 博客园.

ASP.NET MVC中微软已经提供了如何防止跨域攻击的方法。对于传统Webfrom中使用Handler来接受ajax的Post请求数据,如何来防止XSRF攻击呢。这里给大家提供一个简单地方法,和MVC中类似。

 

1.首先需要在你的站点中安装如下的nuget包。可以手动复制dll。

Install-Package Microsoft.AspNet.WebPages -Version 2.0.20710

最新版本的Razor是3.0的,安装WebPages的时候,它依赖于Razor,所以对于framework4.0的项目来说,无法安装WebPages最新版本。需要安装2.0版本。

安装完成后,增加了如下几个dll:

image

2.配置web.config,生成隐藏的token。

需要在system.web节点下增加如下配置:

<machineKey decryption=”AES” validation=”SHA1″ decryptionKey=”435D9CC99471D1E7C70FFEBA5EC71F28048BF9016605B82CC69B091FD317B294″ validationKey=”25C5D98CE093E77C2F886A6D8C6DA8FBC77CD764A1BF49E5D30CD123C5E19553″/>

配置好节点后,需要在.aspx页面的后台代码中增加一个Token生成字段,如果有基类,那么就可以把该部分添加到基类中。

image

我们增加了属性Token,然后使用AntiForgery.GetHtml()来生成一个隐藏的token。然后在页面中绑定该Token。

<form id=”form1″ runat=”server”>
  <%=Token %>
  <div>
  
  </div>
  </form>

3.创建一个接收ajax请求的Handler,加入防止伪造页面提交的代码。

image

 

4.创建一个带有Token的Ajax请求。

image

 

这样就可以防止你的异步请求被XSRF攻击了。

PS:对于很多站点,会有子域名之类的,或者是一个Cookie多个站点共用,就容易出现懂点技术的用户跨站点去伪造请求。

微软开源了.net的很多代码,如果你想看上面的实现原理,那么可以去下载 代码查看。

image

 

希望对你有所帮助。

[转载]10 个强大的JavaScript / jQuery 模板引擎推荐 - Web前端 - ITeye资讯

mikel阅读(1265)

[转载]10 个强大的JavaScript / jQuery 模板引擎推荐 – Web前端 – ITeye资讯.

模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档。由于在开发过程中,网站或应用程序的界面与数据实现分离,大大提升了开发效率,良好的设计也使得代码重用变得更加容易。

本文整理了10 款基于JavaScriptJQuery的模板引擎,希望能对你的开发工作带来一些帮助。

1. NANO

最简单的JQuery模板引擎,完美实现对JSON的解析。

源码 / 演示

2. The “template” binding

该工具通过渲染模板将相关联的DOM元素组织到一起。

源码 / 演示

3. JsViews

下一代的JQuery模板,交互式数据驱动视图,建立在JsRender模板的基础上。

源码 / 演示

4. JsRender

针对高性能和纯字符串渲染进行了优化,无需依赖DOM和jQuery

源码 / 演示

5. google-jstemplate

针对Ajax Web应用程序的简单、强健的浏览器端模板处理工具。

源码 / 演示

6. The jQuery Templates Plugin

一个jQuery模板插件,该插件的开发工作目前处于停滞状态。

源码 / 演示

7. jQote2

这是jQote的第2个版本,是基于jQuery的最强大、通用的客户端模板引擎。

源码 / 演示

8. kite

这是一个基于JavaScript的模板引擎。

源码 / 演示

9. mustache.js

基于JavaScript的Logic-less(无逻辑或轻逻辑)模板。

源码 / 演示

10. Tempo 1.7

Tempo是一个微型JSON渲染引擎,允许你使用纯HTML制作数据模板。

源码 / 演示

英文原文:10 JavaScript and jQuery Templates Engines

[转载]如何编写高效的jQuery代码 - 飞 凡 - 博客园

mikel阅读(1330)

[转载]如何编写高效的jQuery代码 – 飞 凡 – 博客园.

一、不要过度使用JQuery

  1. JQuery速度再快,也无法与原生的JavaScript方法相比,而且建立的JQuery对象包含的信息量很庞大。所以有原生方法可以使用的场合,尽量避免使用jQuery

例如:

$("a").click(function(){
    alert($(this).attr("id"));
});

改良后↓

$("a").click(function(){
    alert(this.id);
});

2. 许多jQuery方法都有两个版本,一个是供jQuery对象使用的版本,另一个是供jQuery函数使用的版本。由于后者不通过jQuery对象操作,所以相对开销较小,速度比较快。

例如:

var $text = $("#text");
var $ts = $text.text();

改良后↓

var $text = $("#text");
var $ts = $.text($text);

这里是用了“$.text()”的内置函数,其他类似的还有“$.data()”等。

 

二、缓存jQuery对象

  查找DOM元素实际上有不小的内存开销,使用选择器的次数应该越少越好,并且尽可能缓存选中的结果,便于以后反复使用。记住,永远不要让相同的选择器出现多次。

例如:

$("#top").find("p.classA");
$("#top").find("p.classB");

改良后↓

var cached = $("#top");
cached.find("p.classA");
cached.find("p.classB");

 

三、少改动DOM结构

如果要多次改动DOM结构,就先把要改动的部分先取出来,改动完成后再放回去。这里的基本思想是在内存中建立你确实想要的东西,最后做一次最有效的更新DOM操作。

例如:

var top_100_list = [...], // 这里是100个字符串的数组  
$mylist = $("#mylist"); 
for (var i=0, l=top_100_list.length; i<l; i++){
    $mylist.append("<li>" + top_100_list[i] + "</li>"); // 100次DOM操作
} 

改良后↓

复制代码
var top_100_list = [...],
$mylist = $("#mylist"),
top_100_li = ""; // 这个变量用来存储变化的字符串
for (var i=0, l=top_100_list.length; i<l; i++){
    top_100_li += "<li>" + top_100_list[i] + "</li>";
} 
$mylist.html(top_100_li);// DOM操作只有这么一次 
复制代码

jQuery编写技巧:


一、选择器择优

选择器是jQuery的基础,如何选择效率最高的选择器,先要了解各种选择器的性能差异。

①ID选择器和标签元素选择器:$(“#ID”); $(“Tag”);

jQuery内部会自动调用浏览器的原生方法(getElementById();,getElementByTagName();),所以执行速度快。

②类选择器:$(“.Class”);

jQuery会遍历所有DOM节点查找class=Class的DOM对象,所以执行速度较慢。

③伪类选择器和属性选择器:$(“:Type”); $(“[Attribute=’Value’]”);

因为浏览器没有针对它们的原生方法,这两种选择器执行速度是最慢的。不过,不排除一些第三方浏览器增加了querySelector()和querySelectorAll()方法,因此会使这类选择器的性能有大幅提高。

 

二、链式写法

$(“div”).find(“h3”).eq(2).html(“Hello”);

采用链式写法时,jQuery会自动缓存每一步的结果,比非链式写法(手动缓存)要快。

 

三、高效循环

循环总是一种比较耗时的操作,JavaScript原生循环方法for和while,要比jQuery的“.each()”快。并且关于for循环,以下这种写法效率最高。

for (var i = 0, len = array.length; i < len; i++) {
  // alert(i);
}

先声明变量,再进行循环操作,效率远比遍历数组“for (var in arr)”高得多,也比循环取得数组长度“for (var i = 0; i < arr.length; i++)”的效率高!

 

四、字符串拼接

字符串的拼接在开发中会经常遇到,用“+=”的方式来拼接字符串的效率非常的低,我们可以利用数组的“.join()”方法。

复制代码
var array = [];

for(var i = 0; i < 10000; i++){
    array[i] = "<input type='button' value='a'>";
}

document.getElementById("one").innerHTML = array.join("");
复制代码

以前我很喜欢用数组的原生的方法“.push()”,其实直接用arr[i]或者arr[arr.length]的方式要快一点,但是差别不是很大。

 

五、页面加载

尽管$(document).ready 确实很有用, 它可以在页面渲染时,其它元素还没下载完成就执行。如果你发现你的页面一直是载入中的状态,很有可能就是$(document).ready函数引起的。 你可以通过将jQuery函数绑定到$(window).load 事件的方法来减少页面载入时的cpu使用率。

$(window).load(function(){
    // 页面完全载入后才初始化的jQuery函数. 
});

它会在所有的html(包括<iframe>)被下载完成后执行。一些特效的功能,例如拖放,视觉特效和动画,预载入隐藏图像等等,都是适合这种技术的场合。

★不是每一次努力都会有收获,但是每一次收获都必须努力,这是一个不公平的不可逆转的命题★

[转载]用《捕鱼达人》去理解C#中的多线程 - 黑树 - 博客园

mikel阅读(1192)

[转载]用《捕鱼达人》去理解C#中的多线程 – 黑树 – 博客园.

线程是进程中某个单一顺序的控制流,是程序运行中的调度单位,是程序执行流的最小 单位,一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。 线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可 与同属一个进程的其它线程共享进程所拥有的全部资源。 线程也有就绪、阻塞和运行三种基本状态。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序进程本身。

CLR中有三种常用创建和管理线程的方式:Thread、ThreadPool、Task,下面用最简单的例子写出自己对这三种方式的理解:

一、Thread

《捕鱼达人》是大家都玩过的游戏,至于游戏怎么设计我也不太清楚,但我想在这里用自己对线程的理解来用线程描述这个游戏。假如屏幕上随机产生两条鱼,并且游来游去,代码如下:
class Fish
      {
            public string Name { get; set; }
 
            public Fish()
            {
                  Name = "小黄鱼" ;
            }
 
            public void Move()
            {
                  Console.WriteLine(string .Format("{0}在游来游去......", Name));
            }
      }
 
      class Program
      {
            static void Main(string[] args)
            {
                  Fish fish = new Fish();
                  Thread t1 = new Thread(() =>
                  {
                        fish.Move();
                  });
                  t1.IsBackground = true;
                  t1.Start();
 
                  Fish fish2 = new Fish() { Name = "大鲨鱼" };
                  Thread t2 = new Thread(() =>
                  {
                        fish2.Move();
                  });
                  t2.IsBackground = true;
                  t2.Start();
 
                  Console.ReadKey();
            }
      }

运行后屏幕如下:
小黄鱼在游来游去……
大鲨鱼在游来游去……
二、ThreadPool
如果鱼潮来临,一下子要产生100条鱼,如果按上面Thread的做法就要开启100条线程,这样对系统资源的损耗太大,这时我们可以用ThreadPool线程池来实现,代码如下:

static void Main(string[] args)
            {
                   Fish fish = new Fish();
                   Fish fish2 = new Fish() { Name = "大鲨鱼" };
                   Fish fish3 = new Fish() { Name = "灯笼鱼" };
                   Fish fish4 = new Fish() { Name = "红鲤鱼" };
                   Fish fish100 = new Fish() { Name = "灯笼鱼" };
                   ThreadPool.QueueUserWorkItem(f => { fish.Move(); });
                   ThreadPool.QueueUserWorkItem(f => { fish2.Move(); });
                   ThreadPool.QueueUserWorkItem(f => { fish3.Move(); });
                   ThreadPool.QueueUserWorkItem(f => { fish4.Move(); });
                   ThreadPool.QueueUserWorkItem(f => { fish100.Move(); });
                   Console.ReadKey();
            }

运行后屏幕如下:
灯笼鱼在游来游去……
大鲨鱼在游来游去……
灯笼鱼在游来游去……
小黄鱼在游来游去……
红鲤鱼在游来游去……
由于多线程是并发执行,由系统分配顺序,所以上面的结果是随机的
三、Task
Task是.Net4.0中新加的功能,由于ThreadPool对池中的线程不好控制,Task用来弥补,比如在鱼在流动的时候,我开了一个枪和炮的线程用来发射子弹捕鱼,鱼中枪后鱼游动的线程就要结束,结束的时候弹出奖励积分,比如小黄鱼弹出1分,大鲨鱼弹出100分,这是就要用到Task对象的ContinueWith方法,该方法可以在线程结束的时候产生一个回调方法,代码如下:

class Program
      {
            static void Main(string[] args)
            {
                  //用来取消小黄鱼线程
                  CancellationTokenSource cts = new CancellationTokenSource ();
 
                  Fish fish = new Fish();
                  Fish fish2 = new Fish() { Name = "大鲨鱼" , Score =100 };
 
                  Task t1 = new Task(() => fish.Move(cts.Token), cts.Token);
                  t1.Start();
                  //小黄鱼被击中后显示积分
                  t1.ContinueWith(fish.ShowScore);
 
                  Task t2 = new Task(() =>fish2.Move(cts.Token), cts.Token);             
                  t2.Start();
                  //大鲨鱼鱼被击中后显示积分
                  t2.ContinueWith(fish2.ShowScore);
 
                  //按任意键发射
                  Console.ReadKey();
 
                  //武器工厂线程池,执行一组任务
                  Gun gun = new Gun();
                  LaserGun laserGun = new LaserGun();
                  TaskFactory taskfactory = new TaskFactory();
                  Task[] tasks = new Task[]
                  {
                        taskfactory.StartNew(()=>gun.Fire()),
                        taskfactory.StartNew(()=>laserGun.Fire())
                  };
                  //执行武器们开火
                  taskfactory.ContinueWhenAll(tasks, (Task) => { });
 
                  //鱼儿们被击中了就会去调显示积分的方法
                  cts.Cancel();
                  Console.ReadLine();
            }
      }
 
      class Fish
      {
            public string Name { get; set; }
            public int Score { get; set; }
 
            public Fish()
            {
                  Name = "小黄鱼" ;
                  Score = 1;
            }
 
            /// <summary>
            /// 游动
            /// </summary>
            public void Move(CancellationToken ct)
            {
                  //如果没有被击中,就一直游阿游,用IsCancellationRequested判断
                  while (!ct.IsCancellationRequested)
                  {
                         Console.WriteLine(string .Format("{0}在游来游去......", Name));
                         Thread.Sleep(1000);
                  }                 
            }
 
            //中枪死亡后显示奖励
            public void ShowScore(Task task)
            {
                   Console.WriteLine(string .Format("{0}中弹了,您得到{1}分......" , Name, Score));
            }
      }
 
      abstract class Weapon
      {
             public string Name { get; set; }
             public abstract void Fire();
      }
 
      class Gun : Weapon
      {
            public Gun()
                  : base()
            {
                  Name = "双射枪" ;
            }
            public override void Fire()
            {
                  Console.WriteLine(string .Format("咻咻咻,{0}向鱼儿们发射子弹......" , Name));
            }
      }
 
      class LaserGun : Weapon
      {
            public LaserGun()
                  : base()
            {
                  Name = "激光炮" ;
            }
            public override void Fire()
            {
                  Console.WriteLine(string .Format("嗖嗖嗖,{0}向鱼儿们发射炮弹......" , Name));
            }
      }

运行后屏幕如下:
大鲨鱼在游来游去……
小黄鱼在游来游去……
大鲨鱼在游来游去……
小黄鱼在游来游去……
大鲨鱼在游来游去……
小黄鱼在游来游去……
按任意键开火后屏幕显示:
大鲨鱼在游来游去……
小黄鱼在游来游去……
大鲨鱼在游来游去……
小黄鱼在游来游去……
大鲨鱼在游来游去……
小黄鱼在游来游去……
咻咻咻,双射枪向鱼儿们发射子弹……
嗖嗖嗖,激光炮向鱼儿们发射子弹……
大鲨鱼中弹了,您得到100分……
小黄鱼中弹了,您得到1分……
总结:
本人技术一般,脑子愚钝,很多复杂的资料看不太懂,所以喜欢用简单的例子帮助自己理解某个知识点,上面的例子有很多的不足之处,大神们要看到不要笑话就行。
用到线程的时候,如果数量少就用Thread,但Thread不太好结束,这时可以考虑用CancellationTokenSource 类的Cancel方法,当要用到很多线程的时候就用线程池ThreadPool,当要用到很多线程且要对对应的线程进行控制和回调的时候就用Task。
有关Thread、ThreadPool、Task的详细资料大家可以看官方的资料。
谢谢阅读,望指点和推荐。

[转载]Java微信公众平台接口封装源码分享 - Myna Wang - 博客园

mikel阅读(1100)

[转载]Java微信公众平台接口封装源码分享 – Myna Wang – 博客园.

前言:

     这篇博客是在三月初动手项目的时候准备写的,但是为了完成项目只好拖延时间写这篇博客,顺便也可以在项目中应用我自己总结的的一些经验。今天看来,这些方法的应用还是可以的,至少实现了我之前的构想。
    写本文的初意是为了让那些跟我一样对微信公众平台有长时间关注的和那些还未了解微信公众平台的Programer,分享些思路以及开发经验,希望对阅览此文的你会有所帮助。
也希望有大神对小八哥的不妥之处进行指点   

鸣谢:感谢以下两位大神的指点http://blog.csdn.net/lyq8479 以及 http://www.cnblogs.com/txw1958 

特别鸣谢:我傻傻的女朋友,这一年没她的支持不管是生活上还是心理上估计我的路会走的更加吃力,欠她的时间太多情太多,只能用“有朝一日”来还吧!!!!!

前期准备:

       几个月前写过一篇公众平台基础接口调用的文章:http://www.cnblogs.com/Codenewbie/p/3360374.html 
    今天准备的是高级接口的调用方法的封装以及Oauth2高级接口的应用测试Demo,高级接口公布的一段时间内,由于对Oauth2协议的不了解,一直受困于此,因此花了一段比较长时间在研究这方面的东西,也请教了上文提到的两位大神。接下来说说我对Oauth2的理解吧:
        OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。(摘自百度百科)  
对公众平台上的Oauth2协议的理解基本如下:
                  
到此处为止是4月4号写的前言,下文将在此刻2014年4月18日23:01:31继续进行
    再叙前言:当看见别人的“”优越于自己的“”的时候请别慌,机会总会来的,这只是人生路上你的一个参考物而已,才20出头,怕啥呀,好好学就是了。@Jeff Li 相信你会看见,你懂我意思的!
遇到了人生中比较重要的选择,我还在甄别这碗汤该怎么熬,熬到什么时候…还是且行且熬吧!

统统走一遍:

   时间追溯到寒假:年前的那段时间因为项目挤得太紧还未实现任何高级功能的接口封装,只记得那天是大年30,听着窗外的鞭炮声,苦逼的我在房间里研究高级 接口,只为来年开发的时候方便一些,那晚也算是搞定了发送客服消息接口,随着时间的流逝,再到如今群发接口和支付接口的发布(此处两个接口还未实现),基 本上接口已封装完成,接下来就跟我一起走一遍流程吧:
     先上项目截图:
                                                                                                       
  com.sedion.basic.util内为基本信息工具:
              1.SendBasicService为自动回复6大类消息的封装
  com.sedion.menu.util内为菜单管理工具:
              1.MenuUtil为增删差自定义菜单的封装
              2.MenuManager为自定义菜单的内容类型管理工具(设置菜单显示的样式和作用)
  com.sedion.wechatapi.util内为基本的工具:
1.CommonUtil内包括 发起https请求并获取结果工具、获取access_token工具、URL编码(utf-8)工具、根据类型判断文件扩展名工具
              2.MyX509TrustManager为证书信任管理器
              3.SignUtil 为验证消息真实性(请求来源于微信)工具类
              4.WeixinUtil包括了接收和发送消息类型初始化以及微信公众平台接口Url的初始化
              5.XmlMessUtil是xml形式消息处理工具类
  com.sedion.advanced.util内为高级接口的封装:
  上文中已提到之前的基础接口总结,本文将不再赘述,接下去,将对已实现的高级接口作一个总结:

1.创建二维码接口 CreateQRCode

public static void main(String[] args) {
// 获取接口访问凭证
String accessToken=getAccessToken("appid", "appsecret").getAccesstoken();
// 创建临时二维码
// gQHN7zoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0pFTUxKVDdsS1Q1UWFOeGtvbTJ3AAIEIn4ZUwMECAcAAA==
WeixinQRCode Temporaryqrcode=createTemporaryQRCode(accessToken, 1800, 1);
System.err.println(Temporaryqrcode.getTicket());
// 创建永久二维码
// gQGx8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL1JrTlIyajNsZ2o3NzlyNXFfRzJ3AAIEGKUZUwMEPAAAAA==
String Permanentqrcode=createPermanentQRCode(accessToken, 2);
System.err.println(Permanentqrcode);
}

2.获取二维码工具 GetQRCode

public static void main(String[] args) {
String ticket="gQGx8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL1JrTlIyajNsZ2o3NzlyNXFfRzJ3AAIEGKUZUwMEPAAAAA==";
String savePath="D:/db";
// 根据ticket换取二维码
getQRCode(ticket, savePath);
}

3.获取用户基本个人信息方法 GetPersoninf

public static void main(String[] args) {
// 获取接口访问凭证
String accessToken=getAccessToken("appid", "appsecret").getAccesstoken();
// 获取用户基本信息
PersonalInf personalInf=getPersonalInf(accessToken, "openId");
System.out.println(personalInf.getOpenid());

// 查询用户所在分组
int groupid=getPersonGroupId(accessToken, "openId");
System.err.println("组id是:"+groupid);
}

4.获取关注者列表 GetUserList

public static void main(String[] args) {
// 获取接口访问凭证
String accessToken=getAccessToken("appid", "appsecret").getAccesstoken();
WeixinUserList weixinUserList=getUserList(accessToken, "");
System.err.println("total:"+weixinUserList.getTotal());
System.err.println("count:"+weixinUserList.getCount());
System.err.println("openid:"+weixinUserList.getOpenIdList());
System.err.println("next_openid:"+weixinUserList.getNextOpenId());
}

5.用户组操作工具 GroupUtil

public static void main(String[] args) {
// 获取接口访问凭证
String accessToken=getAccessToken("appid", "appsecret").getAccesstoken();

// 获取分组列表
List groupList=getGroups(accessToken);
// 循环输出各分组信息
for(WeixinGroup group:groupList){
System.err.println(String.format("ID: %d 名称: %s 用户数: %d", group.getId(),
group.getName(),group.getCount()));
}

// 创建分组
WeixinGroup group=createGroup(accessToken, "学生");
System.err.println(String.format("创建学生组成功: %s id: %d", group.getName(),group.getId()));

// 修改分组
boolean result=updateGroup(accessToken, 100, "傻逼");

// 移动用户分组
boolean result2=removeMemberGroups(accessToken, "openId", 100);

}

6.发送客服消息工具 SendCustomMessage

public static void main(String[] args) {
// 获取接口访问凭证
String accessToken=getAccessToken("appid", "appsecret").getAccesstoken();
// 组装文本客服消息
String jsonTextMsg=MakeCustomMessage.makeTextCustomMessage("openid", "哈哈哈哈");
// 其他类型此处略去,请看源码
// 发送客服消息
sendCustomMessage(accessToken, jsonTextMsg);
}

7.上传下载多媒体文件工具 MediaUtil

public static void main(String[] args) {
// 获取接口访问凭证
String accessToken=getAccessToken("appid", "appsecret").getAccesstoken();
// 上传多媒体文件
WeixinMedia weixinMedia=uploadMedia(accessToken, "image", "http://localhost:8080/wechatapi/upload/sedion.jpg");
System.err.println(weixinMedia.getMediaId());
System.err.println(weixinMedia.getType());
System.err.println(weixinMedia.getCreatedAt());
// 下载多媒体文件
String filePath=getMedia(accessToken, "", "D:/db");
System.err.println(filePath);
}

8.OAuth2授权工具 OAuthUtil

public static void main(String[] args) {
WeixinOauth2Token weixinOauth2Token=getOauth2AccessToken("appid", "appsecret", "code");
System.err.println("weixintoken是:"+weixinOauth2Token);
String accessToken=weixinOauth2Token.getAccessToken();
System.err.println("accestoken是"+accessToken);
String openId=weixinOauth2Token.getOpenId();
System.err.println("openId是"+openId);
SNSUserInfo snsUserInfo=getSNSUserInfo(accessToken, openId);
System.err.println("snsUserInfo是"+snsUserInfo);
}

9.自定义菜单接口

public static void main(String[] args) {
// 第三方用户唯一凭证
String appId = "appid";
// 第三方用户唯一凭证密钥
String appSecret = "appsecret";
// 调用接口获取access_token
AccessToken at = CommonUtil.getAccessToken(appId, appSecret);
if (null != at) {
// 调用接口创建菜单
boolean result = MenuUtil.createMenu(getMenu(), at.getAccesstoken());
// 判断菜单创建结果
if (result)
log.info("菜单创建成功!ok");
else
log.info("菜单创建失败,错误码:" + result);
}
}

10.获取access_token

public static void main(String[] args) {
// 获取接口访问凭证
AccessToken accessToken=getAccessToken("appId", "appSecret");
if (accessToken.getAccesstoken()==null) {
System.out.println("空");
}else {
System.out.println(accessToken.getAccesstoken());
}
}

总结:

上文中草草的将代码复制黏贴了一下,已经到了2014年4月19日00:30:45,不知不觉中这几年的这些夜晚都是这么过来的,熬夜,熬夜,熬夜,其实 我也喜欢睡觉,我也喜欢玩,可是条件不允许,作为一个大三学生党,把自己的大学生涯都压在了代码身上,未来任是扑朔迷离,但深信,吃得苦中苦方为人上人。 此处与各位共勉!

看了这么多,你是不是在问源码呢,源码怎么没有,别急,为了防止小人,不将源码放在git上任大家下载了,求源码者请加入QQ群,源码就在群共享中,群主是本人,有什么问题大家可以一起交流,一起分享!

 

如果你觉得赞就给本博推荐下吧,希望能上精华,如果你是大神那就别搭理本博了

本文只是自我的一个总结,如果对你有所帮助是我的荣幸,文章不妥之处希望指正,大神勿喷请通过留言或关注微信公众帐号codenewbie支持小八哥!若有不妥之处,欢迎指点。

转帖请注明本文出自小八哥的博客(http://www.cnblogs.com/Codenewbie),请尊重他人的辛勤劳动成果,谢谢!

[转载]如何全面解决ECSHOP的jquery冲突_phper老腰_新浪博客

mikel阅读(949)

[转载]如何全面解决ECSHOP的jquery冲突_phper老腰_新浪博客.

主要就是Ecshop的AJAX传输类,transport.js中重写了object的对象原型,从而导致了与jq框架的冲突。

解决:

1. 删除transport.js中587行 – 636行中关于object.prototype.toJSONString的定义

2. 自定义一个方法用于object对象的json序列化

如下

function obj2str(o)

{

  //开始

      var r = [];

   if(typeof o =="string") return "\""+o.replace(/([\'\")/g,]\\])/g,"\\$1").replace(/(\n)/g,"\\n").replace(/(\r)/g,"\\r").replace(/(\t)/g,"\\t")+"\"";

   if(typeof o =="undefined") return "undefined";

   if(typeof o == "object"){   

    if(o===null) return "null";

    else if(!o.sort){

     for(var i in o)

     {  

      if(i!="toJSONString") //增加判断,清除对object原型的定义加入到json中

      r.push("\""+i+"\""+":"+obj2str(o));

     }

     r="{"+r.join()+"}";

    }else{

     for(var i =0;i<o.length;i++)

      r.push(obj2str(o))

     r="["+r.join()+"]"

    }

    return r;

   }

   return o.toString();

  //结束   

}

3. 在模板页和js脚本中所有对于obj.toJSONString()的地方,一概替换为obj2str(obj)

4. 重写好后发现compare.js, 主要重写其中的定时器功能。 将以下代码替换到compare.js中

var Compare = new Object();

Compare = {

  add : function(goodsId, goodsName, type)

  {

    var count = 0;

    for (var k in this.data)

    {

      if (typeof(this.data[k]) == "function")

      continue;

      if (this.data[k].t != type) {

        alert(goods_type_different.replace("%s", goodsName));

        return;

      }

      count++;

    }

    if (this.data[goodsId])

    {

      alert(exist.replace("%s",goodsName));

      return;

    }

    else

    {

      this.data[goodsId] = {n:goodsName,t:type};

    }

    this.save();

    this.init();

  },

  init : function(){

    this.data = new Object();

    var cookieValue = document.getCookie("compareItems");

    if (cookieValue != null) {

      this.data = cookieValue.parseJSON();

    }

    if (!this.compareBox)

    {

      this.compareBox = document.createElement_x("DIV");

      var submitBtn = document.createElement_x("INPUT");

      this.compareList = document.createElement_x("UL");

      this.compareBox.id = "compareBox";

      this.compareBox.style.display = "none";

      this.compareBox.style.top = "200px";

      this.compareBox.align = "center";

      this.compareList.id = "compareList";

      submitBtn.type = "button";

      submitBtn.value = button_compare;

   this.compareBox.appendChild(this.compareList);

      this.compareBox.appendChild(submitBtn);

      submitBtn.onclick = function() {

        var cookieValue = document.getCookie("compareItems");

        var obj = cookieValue.parseJSON();

        var url = document.location.href;

        url = url.substring(0,url.lastIndexOf('/')+1) + "compare.php";

        var i = 0;

        for(var k in obj)

        {

          if(typeof(obj[k])=="function")

          continue;

          if(i==0)

            url += "?goods[]=" + k;

          else

            url += "&goods[]=" + k;

          i++;

        }

        if(i<2)

        {

          alert(compare_no_goods);

          return ;

        }

        document.location.href = url;

      }

      document.body.appendChild(this.compareBox);

    }

    this.compareList.innerHTML = "";

    var self = this;

    for (var key in this.data)

    {

      if(typeof(this.data[key]) == "function")

        continue;

      var li = document.createElement_x("LI");

      var span = document.createElement_x("SPAN");

      span.style.overflow = "hidden";

      span.style.width = "100px";

      span.style.height = "20px";

      span.style.display = "block";

      span.innerHTML = this.data[key].n;

      li.appendChild(span);

      li.style.listStyle = "none";

      var delBtn = document.createElement_x("IMG");

      delBtn.src = "themes/default/images/drop.gif";

      delBtn.className = key;

      delBtn.onclick = function(){

        document.getElementByIdx_x("compareList").removeChild(this.parentNode);

        delete self.data[this.className];

        self.save();

        self.init();

      }

      li.insertBefore(delBtn,li.childNodes[0]);

      this.compareList.appendChild(li);

    }

    if (this.compareList.childNodes.length > 0)

    {

      this.compareBox.style.display = "";

      this.timer = window.setInterval("flowdiv('compareBox')", 50);

    }

    else

    {

      this.compareBox.style.display = "none";

      window.clearInterval(this.timer);

      this.timer = 0;

    }

  },

  save : function()

  {

    var date = new Date();

    date.setTime(date.getTime() + 99999999);

    document.setCookie("compareItems", obj2str(this.data));

  },

  lastScrollY : 0

}

//用于定时器的自动滚动的层

lastScrollY=0;

function flowdiv(domid){

   var diffY;

    if (document.documentElement && document.documentElement.scrollTop)

      diffY = document.documentElement.scrollTop;

    else if (document.body)

      diffY = document.body.scrollTop

    else

      {}

    //alert(diffY);

    percent=.1*(diffY-lastScrollY);

    if(percent>0) percent=Math.ceil(percent);

    else percent=Math.floor(percent);

    document.getElementByIdx_x(domid).style.top=parseInt(document.getElementByIdx_x(domid).style.top)+percent+"px";

    lastScrollY=lastScrollY+percent;

    //alert(lastScrollY);

}