Author Archives: admin

El mouse se mueve a Div, los detalles de la pantalla de la capa flotante y la distancia superior izquierda de la capa pop -up y el div es pesado (código de muestra)

Este artículo presenta principalmente el mouse al DIV, los detalles de visualización de la capa flotante y el código de ejemplo de la distancia superior izquierda de la capa pop -Up y el div. Los amigos que lo necesitan pueden venir como referencia, espero que sea útil para todos

como se muestra a continuación:

Código de copiaEl código es el siguiente:
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
    <title></title>
    <style type=”text/css”>
        .toopTip
        {
            background-color:Yellow;
            border-style:solid;
            border-width:1px;
            border-color:Red;
        }
    </style>
   <script language=”javascript” type=”text/javascript”>
       /*
Si el límite izquierdo del DIV desea superponerse al DIV que muestra el límite superior, entonces debe eliminar el estándar W3C del encabezado del documento
            <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
             “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

       */
       function initEvent() {
           var divArray = document.getElementsByTagName(“div”);
           for (var i = 0; i < divArray.length; i++) {
               divArray[i].onmouseover = createDivDetailOne;
               /*
El incidente que no se puede eliminar del mouse con el DIV original, porque la longitud de ancho del DIV detallado es mayor que el Div original,
Entonces el DIV original está cubierto, y el evento OnMouseOut se activará automáticamente en este momento
               */
               //divArray[i].onmouseout = removeDivDetail;
           }
       }
       function createDivDetailOne() {
// Garantizar la singularidad del Divdetail Div
           var divDetail = document.getElementById(“divDetail”);
           if(divDetail)
           {
               document.body.removeChild(divDetail);
           }
           divObj = document.createElement(“div”);
           divObj.className = “toopTip”;
           divObj.setAttribute(“id”, “divDetail”);
           divObj.style.position = “absolute”;
           divObj.style.width = “200px”;
           divObj.style.height = “100px”;
           var triggerObj = window.event.srcElement;
           divObj.style.top = triggerObj.offsetTop;
           divObj.style.left = triggerObj.offsetLeft;
           divObj.innerHTML = triggerObj.innerText;
           document.body.appendChild(divObj);
// En este momento, el DIV utilizado para detalles ha cubierto el DIV original, por lo que el DIV cubierto debe ser procesado por el evento
           document.getElementById(“divDetail”).onmouseout = function() {
               divObj = this;
               if (!divObj) {
                   return;
               }
               document.body.removeChild(divObj);
           };
       }
       function removeDivDetail() {
           var divObj = document.getElementById(“divDetail”);
           if (!divObj) {
               return;
           }
           document.body.removeChild(divObj);
       }

       window.onload = initEvent;
    </script>

</head>
<body>
    <div id=”divOne” style=”background-color: Fuchsia; width: 100px; height: 100px;” >
        Hello My Js World!
    </div>
    <div id=”divTwo” style=”background-color: Aqua; width: 100px; height: 100px”>
        Welcome to My Js World!
    </div>
    <div id=”divThree” style=”background-color: Gray; width: 100px; height: 100px”>
        THIS IS My Js World!
    </div>
</body>
</html>

JQuery Ejemplo de ejercicio de navegación telescópica

La navegación delgada tiene muchas ventajas. Puede tolerar mucho contenido en un espacio limitado. Hay un buen ejemplo a continuación para usar jQuery. Los amigos interesados ​​pueden referirse a él.
Estudiando recientemente jQuery, intenté hacer esta navegación
 
Descargar:Código

Copiar códigoEl código es el siguiente:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title> Extension Navigation </title>
<link rel=”stylesheet” type=”text/css” href=”nav.css”>
<script type=”text/javascript” src=”jquery-1.10.2.js”></script>
<script type=”text/javascript” src=”nav.js”></script>
</head>
<body>
<div class=”navigator”>
<ul class=”tabs”>
<li class=”tab1″>
<h3> Tarjeta de navegación 1 </h3>
<ul class=”nav1″>
<li> sub -project 1 </li>
<li> sub -project 2 </li>
<li> sub -project 3 </li>
<li> sub -project 4 </li>
</ul>
</li>
<li class=”tab2″>
<h3> Tarjeta de navegación 2 </h3>
<ul class=”nav2″>
<li> sub -project 1 </li>
<li> sub -project 2 </li>
<li> sub -project 3 </li>
<li> sub -project 4 </li>
</ul>
</li>
<li class=”tab3″>
<h3> Tarjeta de navegación 3 </h3>
<ul class=”nav3″>
<li> sub -project 1 </li>
<li> sub -project 2 </li>
<li> sub -project 3 </li>
<li> sub -project 4 </li>
</ul>
</li>
</ul>
</div>

</body>
</html>

código de copiaEl código es el siguiente:
/**
* Author LY 2013-11-11 22:30
**/

* {
margin: 0;
padding: 0;
font-family: “Microsoft Yahei”,”Arial”
}

.navigator {
width: 180px;
display: block;
margin-top: 30px;
margin-left: 30px;
border-top: 10px solid #ddd;
border-bottom: 10px solid #ddd;
border-left: 3px solid #ddd;
border-right: 3px solid #ddd;
background: #ddd;
}
.tabs {
list-style: none;

}

.tabs li {
clear: both;
overflow: auto;
}

.tabs li h3 {
padding: 0;
margin:0;
font-size: 14px;
height: 40px;
line-height: 40px;
text-align: center;
width: 180px;
cursor: pointer;
background: #07f;
color: #fff;
border-bottom: 1px solid #ccc;
}
.tabs li:last-child h3 {
border:none;
}
.tabs li h3.current {
background: #6af;
}
.tabs li ul {
margin-left: auto;
margin-right: auto;
width: 160px;
height: 0px;
list-style: none;
overflow: hidden;
}
.tabs li ul li {
height: 30px;
line-height: 30px;
background: #eee;
padding: 5px;
border-bottom: 1px solid #ccc;
cursor: pointer;
}

Código de copiaEl código es el siguiente:
$(document).ready(function(){
$(“.nav1”).css(“height”,”160px”);
$(“.tabs li h3:first”).addClass(“current”);
$(“.tabs li h3”).click(function() {
$(“.tabs li h3”).removeClass(“current”);
$(this).addClass(“current”);
$(“.tabs li ul”).animate({height:”0″},”fast”);
$(this).next().animate({height:”160″},”slow”);
});
});

jQuery text list rolling upward code

jquery implemented text lists one by one one by one rolling effect

jquery implementation code is as follows:

Copy codecode is as follows:
<script type=”text/javascript”>
$(function(){
 $(“#newly”).hover(function(){
  clearInterval(scrtime);
 },function(){
  scrtime=setInterval(function(){
   $ul=$(“#newly ul”);
   liheight=$ul.find(“li:first”).height();
   $ul.animate({marginTop:”-10px”},1000,function(){
    $ul.find(“li:first”).appendTo(“#newly ul”);
    $ul.find(“li:first”).hide();
    $ul.css(“margin-top”,”0px”);
    $ul.find(“li:first”).show();
   });
  },4200);
 }).trigger(“mouseleave”);
});
</script>

JavaScript: Void (0) Introducción de ejemplo de acción

Al hacer una página, si desea hacer un enlace, no haga nada después de hacer clic o responda a los clics para completar otras cosas, podemos usar JavaScript: Void (0). El siguiente es un método de uso específico. Los amigos interesados ​​pueden referirse a él como referencia hacia abajo
Al hacer una página, si desea hacer un enlace, no haga nada después de hacer clic o responda a hacer clic para completar otras cosas, puede establecer su atributo href = “#”, pero habrá un problema en esto De manera, es decir, cuando la página se roda cuando hace clic, volverá a la parte superior de la página o saltará a la configuración donde se establece la configuración. La experiencia del usuario no es buena.

, la mayoría de las vidas “####”, y también usa “#All” y otros

Código de copiaEl código es el siguiente:
<a href=”javascript:void (0)”> Haga clic aquí para ver el efecto </a>

En realidad, haga clic aquí y no sucederá nada. Entre ellos, JavaScript: Void (0); la forma es un pseudoprotocolo para JavaScript, lo que significa que este enlace no salta a ningún lugar.

Las formas principales de

están usando JavaScript: Void (0): las siguientes son las siguientes:

Código de copiaEl código es el siguiente:
// Haga clic en el enlace sin hacer nada
<a href=”javascript:void(0);” >test</a>
<a href=”javascript:;” >test</a>
<a href=”####”> prueba </a> // usa 2 a

Copiar códigoEl código es el siguiente:
// Después de hacer clic en el enlace, responda a los clics de los clics personalizados del usuario
<a href=”javascript:void(0)” onclick=”doSomething()”>test</a>

.NET Leer RSS y convertirlo en DataTable

Use .NET para leer datos RSS y convertirlos en DataTable. El método es muy simple. Mira el código.

Recientemente necesita recibir un RSS con ASP.NET (C#). RSS son los datos de su propio foro, y RSS agrega otro sub -item al elemento. Así que escribí una lectura universal de RSS y luego aumenté o eliminé sub -items en elementos en el futuro. Este código también se puede reconocer.
hmm … publique el código, registelo.

Código de copiaEl código es el siguiente:
Lea RSS Revolver a DataTable
/// <summary>
/// Obtén RSS y conviértalo en DataTable Back
        /// </summary>
/// <posm name = “FilePath”> Dirección RSS </Param>
        /// <returns></returns>
         public static DataTable GetRss(string filePath)
        {
            DataTable dt = new DataTable();
            WebClient wc = new WebClient();
            Stream srContent = wc.OpenRead(filePath);

            StreamReader sr = new StreamReader(srContent);
            if (!sr.EndOfStream)
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(sr);
                XmlNodeList xnl = xmlDoc.SelectNodes(“rss/channel/item”);
                if (xnl.Count > 0)
                {
{// Agregar un logotipo de columna a DataTable
                        XmlNode xnColumn = xnl[0];
                        XmlNodeList columnsNode = xnColumn.ChildNodes;
                        foreach (XmlNode xn in columnsNode)
                        {
                            DataColumn dc = new DataColumn(xn.Name);
                            dt.Columns.Add(dc);
                        }
} // Agregar una identificación de columna a DataTable

{// Agregar datos a DataTable
                        foreach (XmlNode xnDate in xnl)
                        {
                            DataRow dr = dt.NewRow();
                            for (int i = 0; i < dt.Columns.Count; i++)
                            {
                                XmlNode itemValue = xnDate.SelectSingleNode(dt.Columns[i].ColumnName);
                                dr[i] = itemValue.InnerText;
                            }
                            dt.Rows.Add(dr);
                        }
} // Agregar datos de columna a DataTable
                }
            }
            return dt;
        }

Serie de Jenkins Capítulo 2 -Centos7 Instale Maven, GIT y construye conexiones creíbles con Code Cloud Gitee, realizando la función de descarga y carga sin MVN en el No MVN en

Ver el blog anterior puede hacer clic en [Columna de clasificación] en la parte superior de la parte superior
 

Debido a que la integración e implementación automatizada de Jenkins requiere un entorno JDK, Maven y GIT, también necesitamos instalar Maven y Git.

Este blog explica cómo instalar JDK:https://blog.csdn.net/BiandanLoveyou/article/details/117949441

Center7 Instalación Maven

1. Verifique si hay un entorno Maven en CentOS

[[email protected] ~]# which mvn
/usr/bin/which: no mvn in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/src/jdk/jdk8/bin:/root/bin:/usr/local/src/jdk/jdk8/bin)

consejos ninguno.

2, use el comando wget para descargar el paquete comprimido de Maven

1. Versión de Maven3 (Estación de espejo de código abierto de la Universidad de Tsinghua):https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/ 

2. Para una gestión unificada, descargamos Maven a/usr/local/src/mavenDirectorio. Primero use el comando mkdir para crear.

3, luego en/usr/local/src/maven directorio,Descargar 3.6.3 Comando de paquete de compresión: si se informa un error:-bash: wget: no se encontró ningún comandoluego ejecutar primeroyum -y install wgetInstale el comando wget.

wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz 

4, descompresión

[[email protected] maven]# tar -zxvf  apache-maven-3.6.3-bin.tar.gz 
[[email protected] maven]# ls
apache-maven-3.6.3  apache-maven-3.6.3-bin.tar.gz

5. Configurar variables de entorno.

[[email protected] maven]# vi /etc/profile

Tire al final y aumente esta línea de configuración.presta atención a la configuración de acuerdo con su propio directorio de descompresión

export PATH=$PATH:/usr/local/src/maven/apache-maven-3.6.3/bin

6. Deje que el archivo de configuración entre en vigencia de inmediato

[[email protected] maven]# source /etc/profile

7. Verifique la situación de instalación de Maven

[[email protected] maven]# which mvn
/usr/local/src/maven/apache-maven-3.6.3/bin/mvn

8. Configurar la imagen de espejo de la nube de Alibaba

Ingresamos el directorio conf del directorio de instalación y modificamos el archivo settings.xml, como se muestra en la figura ::

[[email protected] ~]# cd /usr/local/src/maven/apache-maven-3.6.3/conf;ls
logging  settings.xml  toolchains.xml
[[email protected] conf]# vi settings.xml 

Agregue la siguiente configuración al documento:

<mirror>
     <id>alimaven</id>
     <name>aliyun maven</name>
     <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
     <mirrorOf>central</mirrorOf>
</mirror> 

La configuración se muestra en la figura y péguela debajo del nodo de espejos:

9. Especifique la dirección del almacén

Modifique el archivo de configuración Settings.xml para especificar nuestra dirección de almacén.

<localRepository>/usr/local/src/maven/repository</localRepository>

Gráfico de efectos:

Entonces, necesitamos crear el directorio del almacén en el repositorio de directorio Maven

[[email protected] maven]# mkdir repository

OK, ¡MAVEN Instalación de CentOS!

 

CentOS7 Instalar git

1. Verifique si el git está instalado

[[email protected]~]# git -version 
 -Bash: git: no se encontró ningún comando

Luego cree un directorio de instalación de GIT:/usr/local/src/git

2. Instale la dependencia relacionada de Git

yum -y install zlib-devel openssl-devel cpio expat-devel gettext-devel curl-devel perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker

3. En el directorio GIT, descargue el paquete de compresión Git de Github

[[email protected] git]# wget https://github.com/git/git/archive/v2.14.1.zip

4, descompresión

[[email protected] git]# unzip v2.14.1.zip 

5. Instalación.

Crear en el directorio GITinstall Directorio, el directorio para instalar GIT:

[[email protected] git]# mkdir install
[[email protected] git]# ls
git-2.14.1  install  v2.14.1.zip

Ingrese Git-2.14.1 e instale el GIT en el directorio de instalación. El comando es el siguiente:

[[email protected] git]# cd git-2.14.1/
[[email protected] git-2.14.1]# make prefix=/usr/local/src/git/install/ all

6. Continúe ejecutando el comando de instalación.

[[email protected] git-2.14.1]# make prefix=/usr/local/src/git/install/ install

7. Verificación

[[email protected] git-2.14.1]# git --version
git version 1.8.3.1

OK, instale Git bajo el centzo.

y Code Cloud Gitee establece una conexión creíble

1. Cuenta registrada

Código GITEE Dirección oficial de la nube:https://gitee.com/

git y código nube Use el cifrado RSA para verificar la identidad, por lo que se deben generar un par de claves públicas y claves privadas. ¿No entienden el cifrado no simétrico? Mira mi blog:https://blog.csdn.net/BiandanLoveyou/article/details/117524716

Si su git es una versión de Windows, puede ver el blog:https://blog.csdn.net/BiandanLoveyou/article/details/117752102

Nuestro blog explica la versión de Linux.

2. Generar clave pública y clave

Generamos un par de claves públicas y claves privadas localmente en Linux. Tenga en cuenta que la clave pública y la clave privada están emparejadas.

ssh -keygen -t rsa -c "su dirección de buzó[email protected]"

y luego regrese directamente 3 veces.

resultado:

Ingresemos /Root/.SSH para ver nuestra clave pública y los archivos de clave privada. .Pub es una clave pública e ID_RSA es una clave privada.

[[email protected] .ssh]# cd /root/.ssh;ls
id_rsa  id_rsa.pub

 

3. Agregue la clave pública a nuestra nube de código y establezca una conexión creíble con GITEE

Use el comando gato o cola para leer la clave pública:

[[email protected] .ssh]# cat id_rsa.pub 

y luego copie toda la clave públicaincluyendo el SSH-RSA anterior y su dirección de correo electrónico detrás

y luego abra la nube de código registradohttps://gitee.com/Avatar personal en la esquina superior derecha Haga clic [Configuración].

Luego busque la tecla pública SSH en la barra de menú a la izquierda y haga clic. Agregue la clave pública. Los archivos de la clave pública acaban de generarTodo el contenido (incluido el SSH-RSA anterior y su dirección de correo electrónico detrás), Pega en.

Operación de verificación:

Verificación:

ssh -T [email protected]

representaciones: si la salida es la siguiente, significa bien. Ha autenticado con éxito, pero Gitee.com no proporciona acceso de shell.

Haga clic en Sí para configurar la conexión creíble del host actual con GITEE.

También necesitamos hacer un trabajo, es decir, Linux agrega permisos Git localmente.

git config -user -global user.emama "Su dirección de buzón" 

 git config -user -global user.name "Your Name"

y luego inicialmente git

Gráfico de efecto

git init

:

En este punto, Git está configurado en nuestros CentOS.

Función de implementación y carga de git y gitee

1, descargar

Crear un proyecto en Code Cloud. En la esquina superior derecha, hay A + al lado del avatar, haga clic en [Nuevo almacén]

Por ejemplo, cree un elemento de prueba:

Luego ingrese la página de administración del proyecto, haga clic en [Clone/Descargar], seleccione SSH y copie la dirección.

El proyecto en el Terminal Cloud de Terminal de clonación 82 a Linux Local (descargar), primero creamos un directorio de espacio de trabajo en el directorio GIT para almacenar uniformemente el proyecto:

Gráfico de efecto

[[email protected] git]# mkdir wordspace
[[email protected] git]# cd wordspace/
[[email protected] wordspace]# git clone [email protected]:biandanLoveyou/linux-test-project.git

:

De esta manera, la función clon (descarga) se realiza.

2, Sube

Ingresamos a un buen proyecto y creamos un documento de Helloworld

[[email protected] wordspace]# cd linux-test-project/
[[email protected] linux-test-project]# vi HelloWorld

Ingrese el siguiente contenido:

hoy es hora de Beijing: 16 de junio de 2021 
 ¡Hola! Si ve este mundo, ¡significa que su Linux puede vincular para darle a GiteeEssy! 
 ¡BUENA SUERTE! ¡Nos vemos!

Luego ingrese el comando [git add.] Tenga en cuenta que hay un espacio y un punto. Este comando solo agrega el archivo de cambio a la versión git:

[[email protected] linux-test-project]# git add .

Luego puede ingresar las instrucciones para enviar (no requerido). Esta operación es agregar esta presentación al caché GIT, y no se envía a GITEE:

[[email protected]Linux-test-Project]# git commit -m "Subido a Gitee con Linux por primera vez, ¡por favor, cuídalo!"

Finalmente, empuje al servidor Gitee.

[[email protected] linux-test-project]# git push origin master

resultado:

Luego lo confirmamos en Gitee.

Haga clic para abrir:

No hay problema, hierro viejo!

source

JavaScript’s recursive and cycle example introduction

For different types of problems that need to be repeatedly calculated, there are two methods: cycle and recursive, which can give more intuitive and simple solutions. The following is a detailed introduction to the recursive and cycle of JavaScript. Interested friends can be able to Understand
recursive and cycle

For different types of problems that need to be repeatedly calculated, the two methods of cycle and recursive have their own strengths, which can give more intuitive and simple solutions. On the other hand, the method of circulation and recursive can be converted to each other. Any cycle of code can be rewritten recursively to achieve the same functions; vice versa. Under the premise of losing its universality, the circulation and recursive can be summarized with the following pseudo -code, respectively.

pseudo -code format description: The loop is in the form of a while; the variable is not defined; the assignment is used: =; conditional expression and execution sentences are written into functions, and related values are written in brackets. In terms of other grammar, try to get closer to the norms of JavaScript.

Copy codecode is as follows:
//pseudo code of a loop
// While form
function loop(arguments){
// The initial value of the result
result:=initial_value;

While (Condition (variable, arguments)) {// cycle conditions may only be arguments, or to facilitate the introduction of cycle variables
// Calculate the results. The parameters include the previous results, the current circulation variable and external variables
result:=calculate(result, variable, extern_variables);
// Affect the external environment of the function, that is, modify the external variable
changeStatus(result, variable, extern_variables);
// After executing the statements in the cycle, modify the parameter or circular variable.
modify_arguments_variable(arguments, variable);
}
// Back results
return result;
}

Similarly, we give a pseudo -code for recursion functions.

Copy codecode is as follows:
//pseudo code of a recursion
function recursion(arguments){
// The following code is the structure part of the control function repeatedly called.
// Get new parameters that call this function again, which may be multiple arguments values.
// C corresponding CorITION (Variable, Arguments) and Modify_arguments_variable (ARGUMENTS, VARIABLE).
new_arguments:=conditional_get_next(arguments);
// Each group of new parameters, call the function itself.
results:=recursion(new_arguments);

// The code below is the functional part of each call running
// Calculate the result. Involved the previous results, current circulation variables and external variables.
// Result: = callculating (result, variable, extern_variables) in the cycle.
result:=calculate(arguments, extern_variables);
result:=combine(result, results);
// Affect the external environment of the function, that is, modify the external variable
changeStatus(result, arguments, extern_variables);
return result;
}

Profting two code comparison, we can see that the cycle and recursive composition have similar compositions. By changing the order and appropriate transformation, any cycle can be implemented in a recursive manner. When the program is simple, this conversion is easy to see. For example, the following simple accumulated sum of sum of summoning functions:

Copy codecode is as follows:
//loop
function sum(num){
var result=1;
while (num>1){
result+=num;
num–;
}
return result;
}

Corresponding to recursive form:

Copy codecode is as follows:
//recursion
function sum2(num){
if (num>1){
return num+sum(num-1);
}else{
return 1;
}
}

Conversely, most recursive programs can also be implemented directly by cycle. Below is a function of a cycle form of the maximum number of contracts.

Copy codecode is as follows:
function gcd2(a, b){
var temp;
if (a<b){
temp=a;
a=b;
b=temp;
}
var c=a%b;
while (c!==0){
a=b;
b=c;
c=a%b;
}
return b;
}

However, the conversion from recursion to cycle is not so easy. The new parameter part of this function is called again in the recursive pseudo -code

new_arguments:=conditional_get_next(arguments);

is more flexible than the corresponding part of the cycle. It can be recursively divided into two categories according to the number of parameter arrays (all parameters required by the function). The first category is the number of parameter arrays fixed, which can be converted into a cycle, such as the example of the Fibonacci quota and the largest division; the second category is the number of parameter arrays is uncertain -just like when traversing a picture or tree Then, each point has any adjacent points -the recursive cannot be directly converted into a cycle.

Because the cycle can only be duplicated by one dimension, recursion can traverse the two -dimensional structure. For example, in a tree, a node has both its sub -nodes and nodes of the same level. A simple one -dimensional cycle cannot be traversed in both directions.

But if we use some data structures to remember some information at the location of the location in the cycle, the second type of recursive can also be implemented with cycle.

Let’s practice the conclusions observed through an example. HTML5 defines a new method GetelementsByClassName (names) for Document and Element, and returns all Elements with a given Class value. Some browsers, including Firefox3, have supported this method. Let’s use a recursion method to give a weak function, and then rewrite it with a cycle method.

Copy codecode is as follows:
var getElementsByClass={};

// ELEM is a htmlelement
// name is a single class name
// Return all the CLASS attributes containing ELEM include an array of Element with a given name
getElementsByClass.recursion1=function (elem, name){
var list=[];
function getElements(el){
if (el.className.split(‘ ‘).indexOf(name)>-1){
list.push(el);
}
for (var i=0, c=el.children; i<c.length; i++){
getElements(c[i]);
}
}
getElements(elem);
return list;
}

, as mentioned earlier, in order to remember the location information of the node in the cycle, we need a data structure that can implement the following methods.

push (object) // Write a object.

Objectpop () // Read a recently written object and delete it from the data structure.

ObjectGet () // Read a recently written object without changing the content of the data structure.

stack is such a data structure that is followed first. The Array object in JavaScript supports the first two methods, we can add the third method to it.

Use a circular version:

Copy codecode is as follows:
getElementsByClass.loop1 = function(elem, name){
//use a js array as the basis of a needed stack
var stack = [];
stack.get = function(){
return stack[stack.length – 1];
}

var list = [];
//the business logic part. put the eligible element to the list.
function testElem(el){
if (el.className.split(‘ ‘).indexOf(name) > -1) {
list.push(el);
}
}
//check the root element
testElem(elem);
//initialize the stack
stack.push({
pointer: elem,
num: 0
});
var parent, num, el;
while (true) {
parent = stack.get();
el = parent.pointer.children[parent.num];
if (el) {//enter a deeper layer of the tree
testElem(el);
stack.push({
pointer: el,
num: 0
});
}
else {//return to the upper layer
if (stack.pop().pointer === elem) {
break;
}
else {
stack.get().num += 1;
}
}
}

return list;
}

summarize. All cycles can be achieved with recursion; all recursion can be implemented with cycle. What kind of method is used, which is more convenient and intuitive and user’s preferences under the specific issues.

efficiency

In terms of performance, recursion is not as good as cycling. In addition to the overhead of multiple function calls, in some cases, recursion will bring unnecessary repeated calculations. Taking the recursive procedures of the Fibonacci quota as an example. At the N (n), from the N-2 item, each item is repeatedly calculated. The smaller the number, the more repeated times. The number of times to.

B(i)=1; i=n, n-1

B(i)=B(i+1)+B(i+2); i<n-1

So, B (i) forms an interesting inverse Fibona. Seeking A (n): there is:

B(i)=A(n+1-i)

From a different angle, it makes C (i) the number of additions required for A (i), and

C(i)=0; i=0, 1

C(i)=1+C(i-1)+C(i-1); i>1

Order d (i) = c (i) +1, there is

D(i)=1; i=0, 1

D(i)=D(i-1)+D(i-1)

So D (i) forms a Fibonacci series. It can also be drawn:

C(n)=A(n+1)-1

and A (N) are growth in geometric levels, which will become very amazing when N is larger when N is larger. Corresponding to this adopt a loop program, there are

b (n) = 1; n is any value

C(n)=0; n=0, 1

C(n)=n-1; n>1

Therefore, when n is large, the previously given cyclic program is much faster than the recursive program.

Like the cycle in the previous section, this defect in recursive can also be made up. We only need to remember the items that have been calculated. When you find higher items, we can directly read the previous items. This technology is very common in recursion, known as “Memorization”.

Below is the recursive algorithm of seeking Fibonacci quota with storage technology.

Copy codecode is as follows:
//recursion with memorization
function fibonacci4(n){
var memory = []; //used to store each calculated item
function calc(n){
var result, p, q;
if (n < 2) {
memory[n] = n;
return n;
}
else {
p = memory[n – 1] ? memory[n – 1] : calc(n – 1);
q = memory[n – 2] ? memory[n – 2] : calc(n – 2);
result = p + q;
memory[n] = result;
return result;
}
}
return calc(n);
}

jquery click ([data], Fn) usage example introduction

Probably means that the click event of each matching element is triggered. This article introduces the use of jQuery Click ([data], Fn) in detail through an example. Interested friends can refer to it, I hope to have something to everyone, I hope to have something to everyone. help
click([[data],fn])
Return value: jquery
Overview
Trigger a click event of each matching element.

This function calls all functions that are bound to the CLICK event.

parameter
fnFunctionV1.0
The processing function bound in each matching element event.

[data],fnString,FunctionV1.4.3
Data: CLick ([Data], Fn) can be transmitted into the data supply function FN processing.

fn: The processing function bound to each matching element event.

sample
Description:
Trigger a click event in all paragraphs in the page

jquery code:
$ (“p”). CLICK (); Description:
Hide all paragraphs in the page after clicking.

jquery code:
$ (“p”). CLICK (function () {$ (this) .hide ();}); the above is the content of the jQuery reference manual. Parameter detailed description

parameter data is passed to an additional data object to the event object as an extra.data attribute value
Parameter FN is a processing function that is bound to an event in each selection element

Copy codecode is as follows:
<!DOCTYPE html>
<html>
<head><meta http-equiv=”Content-Type” content=”text/html;charset=utf-8″ /><meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7″ /><title>
jquery [data] parameter instructions
</title><link href=”css/main.css” type=”text/css” rel=”stylesheet” />
<script src=”jquery-1.8.3.min.js” type=”text/javascript”></script>

<script type=”text/javascript”>
$(function(){
var message = “Pass the information to the Fn function”;
$ (“. TXT”). CLICK ({msg: message}, function (event) {$ (“# IDTIP”). Show (). Html (every.data.msg);}); // Settings text
});
</script>
</head>
<body>
<input class=”txt”></div>
<div id=”idTip”></div>
</body>
</html>

Android automatically adjusts the instance code of the font size according to the resolution

Android automatically adjusts the instance code of the font size according to the resolution, friends who need it can refer to it

mobile phone equipment is too much and the resolution is different. Seeing most of the adaptive fonts on the Internet is to define Values320 × 480 or Value-HDPI to process it.

The first one is miserable. The resolution of many devices is different. Do you have to define each one?

uses the second one to have no effect in the tablet.

Last code is convenient and fast. Essence Essence

[java]

Copy codecode is as follows:
// Traversing settings fonts
PUBLIC Static Void ChangeViewSize (ViewGroup ViewGroup, Int Screenwidth, Int Screenheight) {// Pass to the top layer Layout, screen width, screen height
        int adjustFontSize = adjustFontSize(screenWidth,screenHeight);
        for(int i = 0; i<viewGroup.getChildCount(); i++ ){
            View v = viewGroup.getChildAt(i);
            if(v instanceof ViewGroup){
                changeViewSize((ViewGroup)v,screenWidth,screenHeight);
} else if (v instanceof Button) {// button to increase this must be placed on TextView, because Button has also inherited TextView
                ( (Button)v ).setTextSize(adjustFontSize+2);
            }else if(v instanceof TextView){
if (v.getid () == r.id.title_msg) {// top title
                    ( (TextView)v ).setTextSize(adjustFontSize+4);
                }else{
                    ( (TextView)v ).setTextSize(adjustFontSize);
                }
            }
        }
    }

 
// Get the font size
public static int adjustFontSize(int screenWidth, int screenHeight) {
        screenWidth=screenWidth>screenHeight?screenWidth:screenHeight;
        /**
* 1. Get the view width in the ONSIZECHANGED of the view. Generally, the default width is 320, so calculate a zoom ratio
Rate = (Float) W/320 W is the actual width
2. Then Paint.SettextSize ((int) (8*Rate)) when setting font size;
Actual font size = default font size x rate
         */
int Rate = (int) (5*(float) screenwidth/320); // It is more suitable for me to test this multiple, of course, you can modify it before modifying it before modifying
RETURN RATE <15? 15: Rate; // The font is too small and not good -looking
}

// Traversing settings fonts
PUBLIC Static Void ChangeViewSize (ViewGroup ViewGroup, Int Screenwidth, Int Screenheight) {// Pass to the top of Activity, screen width, screen height
  int adjustFontSize = adjustFontSize(screenWidth,screenHeight);
  for(int i = 0; i<viewGroup.getChildCount(); i++ ){
   View v = viewGroup.getChildAt(i);
   if(v instanceof ViewGroup){
    changeViewSize((ViewGroup)v,screenWidth,screenHeight);
} Else If (VINSTANCEOF BUTTON) {// button to increase this must be placed on TextView, because Button has also inherited TextView
    ( (Button)v ).setTextSize(adjustFontSize+2);
   }else if(v instanceof TextView){
if (v.getid () == r.id.title_msg) {// top title
     ( (TextView)v ).setTextSize(adjustFontSize+4);
    }else{
     ( (TextView)v ).setTextSize(adjustFontSize);
    }
   }
  }
 }

// Get the font size
public static int adjustFontSize(int screenWidth, int screenHeight) {
  screenWidth=screenWidth>screenHeight?screenWidth:screenHeight;
  /**
* 1. Get the view width in the viewChanged in the view. Generally, the default width is 320, so calculate a zoom ratio
rate = (Float) W/320 W is the actual width
2. Then Paint.SettextSize ((int) (8*Rate)) when setting font size;
Actual font size = default font size x rate
   */
int Rate = (int) (5*(float) screenwidth/320); // I test this multiples by myself is more suitable, of course you can test it before modifying it before modifying
Return rate <15? 15: rate; // The font is too small and it doesn’t look good
}

Finally, just call the ChangeViewSize after the onCreate of Avtivity. Essence Essence The text is large, so its corresponding background is big, so the background picture of the control of the control is recommended to use the 9 -palace type picture, which looks comfortable.
Another additional, if you want to browse on a tablet computer, you are not hindered. Please add the manifest node (DTD is recommended to put it on the Application node) in the Androidmanifest.xml file:
[java]

Copy codecode is as follows:
<supports-screens
        android:anyDensity=”true”
        android:largeScreens=”true”
        android:normalScreens=”true”
        android:smallScreens=”true” 
        android:resizeable=”true”/>

<supports-screens
        android:anyDensity=”true”
        android:largeScreens=”true”
        android:normalScreens=”true”
        android:smallScreens=”true”
        android:resizeable=”true”/>

An explanation of the audio file information with PHP read and write (support WMA and MP3)

This article is a detailed analysis of PHP reading and writing audio file information. For friends who need it, please refer to
Copy codecode is as follows:
<?php
// AudioExif.class.php
// Use PHP to read and write the head information of the audio file
// Currently only supports WMA and MP3 formats, and only supports a few common head information
//
// Write information support: title (name), Artist (artist), Copyright (copyright), description
// Year (age), Genre (genre), albumtitle (album title)
// Among them, MP3 and WMA are slightly different, and there may be more information returned, but only the above information can be written
// MP3 also supports track (track number writing)
// Support ID3v1 for the MP3 file to support ID3v2. When reading, V2 is preferred. When writing, you will always write V1. If necessary
//
// Usage explanation: (Because WMA uses unicode access, it also needs mb_convert_encoding () expansion
// Back data and writing data are codes of ANSI, that is, what is stored (Chinese_GB2312)
//
// require (‘AudioExif.class.php’);
// $AE = new AudioExif;
// $file = ‘/path/to/test.mp3’;
//
// 1. Check whether the file is complete (only for wma, MP3 always returns true)
//
// $AE->CheckSize($file);
//
// 2. Read information, the return value consists of information, the key name explanation see above
//
// print_r($AE->GetInfo($file));
//
// 3. Write information, the second parameter is a hash array, key-> value, please refer to the top, MP3 also supports Track
// Requires the file path of the first parameter to be written by this program
// $ Pa = ARRAY (‘Title’ => ‘New Title’, ‘Albumtitle’ => ‘New Album Name’);
// $AE->SetInfo($file, $pa);
//
//
// Others: This plug -in spent a lot of time to collect file formats and web pages of Focusing on WMA and MP3. I hope it will be useful to everyone.
// In fact, there are already many similar procedures on the Internet, but there are too few for WMA. You can only pass M $ under the WIN platform
// API to operate, and MP3 rarely can operate in the UNIX/Linux command line, so I specially wrote this module
//
// If you find the bug or submit a patch or improve it to make it more robust, please tell me.
// (The file format and structure of ID3 and WMA should be found on the Internet)
//
if (!extension_loaded(‘mbstring’))
{
  trigger_error(‘PHP Extension module `mbstring` is required for AudioExif’, E_USER_WARNING);
  return true;
}
// the Main Class
class AudioExif
{
  // public vars
  var $_wma = false;
  var $_mp3 = false;
  // Construct
  function AudioExif()
  {
    // nothing to do
  }
  // check the filesize
  function CheckSize($file)
  {
    $handler = &$this->_get_handler($file);
    if (!$handler) return false;
    return $handler->check_size($file);
  }
  // get the infomations
  function GetInfo($file)
  {
    $handler = &$this->_get_handler($file);
    if (!$handler) return false;
    return $handler->get_info($file);
  }
  // write the infomations
  function SetInfo($file, $pa)
  {
    if (!is_writable($file))
    {
      trigger_error(‘AudioExif: file `’ . $file . ‘` can not been overwritten’, E_USER_WARNING);
      return false;
    }
    $handler = &$this->_get_handler($file);
    if (!$handler) return false;
    return $handler->set_info($file, $pa);
  }
  // private methods
  function &_get_handler($file)
  {
    $ext = strtolower(strrchr($file, ‘.’));
    $ret = false;
    if ($ext == ‘.mp3’)
    {  // MP3
      $ret = &$this->_mp3;
      if (!$ret) $ret = new _Mp3Exif();
    }
    else if ($ext == ‘.wma’)
    {  // wma
      $ret = &$this->_wma;
      if (!$ret) $ret = new _WmaExif();
    }
    else
    {  // unknown
      trigger_error(‘AudioExif not supported `’ . $ext . ‘` file.’, E_USER_WARNING);
    }
    return $ret;
  }
}
// DBCS => gb2312
function dbcs_gbk($str)
{
  // strip the last “”
  $str = substr($str, 0, -2);
  return mb_convert_encoding($str, ‘GBK’, ‘UCS-2LE’);
}
// gb2312 => DBCS
function gbk_dbcs($str)
{
  $str  = mb_convert_encoding($str, ‘UCS-2LE’, ‘GBK’);
  $str .= “”;
  return $str;
}
// file exif
class _AudioExif
{
  var $fd;
  var $head;
  var $head_off;
  var $head_buf;

  // init the file handler
  function _file_init($fpath, $write = false)
  {
    $mode = ($write ? ‘rb+’ : ‘rb’);
    $this->fd = @fopen($fpath, $mode);
    if (!$this->fd)
    {
      trigger_error(‘AudioExif: `’ . $fpath . ‘` can not be opened with mode `’ . $mode . ‘`’, E_USER_WARNING);
      return false;
    }
    $this->head = false;
    $this->head_off = 0;
    $this->head_buf = ”;
    return true;
  }
  // read buffer from the head_buf & move the off pointer
  function _read_head_buf($len)
  {
    if ($len <= 0) return NULL;
    $buf = substr($this->head_buf, $this->head_off, $len);
    $this->head_off += strlen($buf);
    return $buf;
  }
  // read one short value
  function _read_head_short()
  {
    $ord1 = ord(substr($this->head_buf, $this->head_off, 1));
    $ord2 = ord(substr($this->head_buf, $this->head_off+1, 1));
    $this->head_off += 2;
    return ($ord1 + ($ord2<<8));
  }
  // save the file head
  function _file_save($head, $olen, $nlen = 0)
  {
    if ($nlen == 0) $nlen = strlen($head);
    if ($nlen == $olen)
    {
      // shorter
      flock($this->fd, LOCK_EX);
      fseek($this->fd, 0, SEEK_SET);
      fwrite($this->fd, $head, $nlen);
      flock($this->fd, LOCK_UN);
    }
    else
    {
      // longer, buffer required
      $stat = fstat($this->fd);
      $fsize = $stat[‘size’];
// BUF Required (4096?) Should not NLEN -OLEN> 4096, right?
      $woff = 0;
      $roff = $olen;
      // read first buffer
      flock($this->fd, LOCK_EX);
      fseek($this->fd, $roff, SEEK_SET);
      $buf = fread($this->fd, 4096);
      // seek to start
      fseek($this->fd, $woff, SEEK_SET);
      fwrite($this->fd, $head, $nlen);
      $woff += $nlen;
      // seek to woff & write the data
      do
      {
        $buf2 = $buf;
        $roff += 4096;
        if ($roff < $fsize)
        {
          fseek($this->fd, $roff, SEEK_SET);
          $buf = fread($this->fd, 4096);       
        }
        // save last buffer
        $len2 = strlen($buf2);
        fseek($this->fd, $woff, SEEK_SET);
        fwrite($this->fd, $buf2, $len2);
        $woff += $len2;
      }
      while ($roff < $fsize);
      ftruncate($this->fd, $woff);
      flock($this->fd, LOCK_UN);
    }
  }
  // close the file
  function _file_deinit()
  {
    if ($this->fd)
    {
      fclose($this->fd);
      $this->fd = false;
    } 
  }
}
// wma class
class _WmaExif extends _AudioExif
{
  var $items1 = array(‘Title’, ‘Artist’, ‘Copyright’, ‘Description’, ‘Reserved’);
  var $items2 = array(‘Year’, ‘Genre’, ‘AlbumTitle’);
  // check file size (length) maybe invalid file
  function check_size($file)
  {
    $ret = false;
    if (!$this->_file_init($file)) return true;
    if ($this->_init_header())
    {
      $buf = fread($this->fd, 24);
      $tmp = unpack(‘H32id/Vlen/H8unused’, $buf);
      if ($tmp[‘id’] == ‘3626b2758e66cf11a6d900aa0062ce6c’)
      {
        $stat = fstat($this->fd);
        $ret = ($stat[‘size’] == ($this->head[‘len’] + $tmp[‘len’]));
      }
    }
    $this->_file_deinit();
    return $ret;
  }
  // set info (save the infos)
  function set_info($file, $pa)
  {
    // check the pa
    settype($pa, ‘array’);
    if (!$this->_file_init($file, true)) return false;
    if (!$this->_init_header())
    {
      $this->_file_deinit();
      return false;
    }

    // parse the old header & generate the new header
    $head_body = ”;
    $st_found = $ex_found = false;
    $head_num = $this->head[‘num’];
    while (($tmp = $this->_get_head_frame()) && ($head_num > 0))
    {
      $head_num–;
      if ($tmp[‘id’] == ‘3326b2758e66cf11a6d900aa0062ce6c’)
      {  // Standard Info
        // 1-4
        $st_found = true;
        $st_body1 = $st_body2 = ”;      
        $lenx = unpack(‘v5’, $this->_read_head_buf(10));
        $tmp[‘len’] -= 34;  // 10 + 24
        for ($i = 0; $i < count($this->items1); $i++)
        {
          $l = $lenx[$i+1];
          $k = $this->items1[$i];
          $tmp[‘len’] -= $l;
          $data = $this->_read_head_buf($l);
          if (isset($pa[$k])) $data = gbk_dbcs($pa[$k]);
          $st_body2 .= $data;
          $st_body1 .= pack(‘v’, strlen($data));
        }
        // left length
        if ($tmp[‘len’] > 0) $st_body2 .= $this->_read_head_buf($tmp[‘len’]);
        // save to head_body
        $head_body .= pack(‘H32VH8’, $tmp[‘id’], strlen($st_body1 . $st_body2)+24, $tmp[‘unused’]);
        $head_body .= $st_body1 . $st_body2; 
      }
      else if ($tmp[‘id’] == ’40a4d0d207e3d21197f000a0c95ea850′)
      {  // extended info
        $ex_found = true;

        $inum = $this->_read_head_short();
        $inum2 = $inum;
        $tmp[‘len’] -= 26;  // 24 + 2
        $et_body = ”;
        while ($tmp[‘len’] > 0 && $inum > 0)
        {
          // attribute name
          $nlen = $this->_read_head_short();
          $nbuf = $this->_read_head_buf($nlen);
          // the flag & value  length
          $flag = $this->_read_head_short();
          $vlen = $this->_read_head_short();
          $vbuf = $this->_read_head_buf($vlen);
          // set the length
          $tmp[‘len’] -= (6 + $nlen + $vlen);
          $inum–;
          // save the data?
          $name = dbcs_gbk($nbuf);
          $k = substr($name, 3);
          if (in_array($k, $this->items2) && isset($pa[$k]))
          {
            $vbuf = gbk_dbcs($pa[$k]);
            $vlen = strlen($vbuf);
            unset($pa[$k]);
          }
          $et_body .= pack(‘v’, $nlen) . $nbuf . pack(‘vv’, $flag, $vlen) . $vbuf;
        }
        // new tag insert??
        foreach ($this->items2 as $k)
        {
          if (isset($pa[$k]))
          {
            $inum2++;
            $nbuf = gbk_dbcs(‘WM/’ . $k);
            $nlen = strlen($nbuf);
            $vbuf = gbk_dbcs($pa[$k]);
            $vlen = strlen($vbuf);
            $et_body .= pack(‘v’, $nlen) . $nbuf . pack(‘vv’, 0, $vlen) . $vbuf;
          }
        }
        // left buf?
        if ($tmp[‘len’] > 0) $et_body .= $this->_read_head_buf($tmp[‘len’]);
        // save to head_body
        $head_body .= pack(‘H32VH8v’, $tmp[‘id’], strlen($et_body)+26, $tmp[‘unused’], $inum2);
        $head_body .= $et_body; 
      }
      else
      {
        // just keep other head frame
        $head_body .= pack(‘H32VH8’, $tmp[‘id’], $tmp[‘len’], $tmp[‘unused’]);
        if ($tmp[‘len’] > 24) $head_body .= $this->_read_head_buf($tmp[‘len’]-24);
      }
    }
    // st not found?
    if (!$st_found)
    {
      $st_body1 = $st_body2 = ”;
      foreach ($this->items1 as $k)
      {
        $data = (isset($pa[$k]) ? gbk_dbcs($pa[$k]) : “”);
        $st_body1 .= pack(‘v’, strlen($data));
        $st_body2 .= $data;
      }

      // save to head_body
      $head_body .= pack(‘H32Va4’, ‘3326b2758e66cf11a6d900aa0062ce6c’, strlen($st_body1 . $st_body2)+24, ”);
      $head_body .= $st_body1 . $st_body2;
      $this->head[‘num’]++;
    }
    // ex not found?
    if (!$ex_found)
    {
      $inum = 0;
      $et_body = ”;
      foreach ($this->items2 as $k)
      {
        $nbuf = gbk_dbcs(‘WM/’ . $k);
        $vbuf = (isset($pa[$k]) ? gbk_dbcs($pa[$k]) : “”);
        $et_body .= pack(‘v’, strlen($nbuf)) . $nbuf . pack(‘vv’, 0, strlen($vbuf)) . $vbuf;
        $inum++;
      }
      $head_body .= pack(‘H32Va4v’, ’40a4d0d207e3d21197f000a0c95ea850′, strlen($et_body)+26, ”, $inum);
      $head_body .= $et_body;
      $this->head[‘num’]++;
    } 
    // after save
    $new_len = strlen($head_body) + 30;
    $old_len = $this->head[‘len’];
    if ($new_len < $old_len)
    {
      $head_body .= str_repeat(“”, $old_len – $new_len);
      $new_len = $old_len;
    }
    $tmp = $this->head;
    $head_buf = pack(‘H32VVVH4’, $tmp[‘id’], $new_len, $tmp[‘len2’], $tmp[‘num’], $tmp[‘unused’]);
    $head_buf .= $head_body;
    $this->_file_save($head_buf, $old_len, $new_len);
    // close the file & return
    $this->_file_deinit();
    return true;
  }
  // get info
  function get_info($file)
  {
    $ret = array();
    if (!$this->_file_init($file)) return false;
    if (!$this->_init_header())
    {
      $this->_file_deinit();
      return false;
    }
    // get the data from head_buf
    $head_num = $this->head[‘num’];  // num of head_frame
    while (($tmp = $this->_get_head_frame()) && $head_num > 0)
    {
      $head_num–;
      if ($tmp[‘id’] == ‘3326b2758e66cf11a6d900aa0062ce6c’)
      {  // Standard Info
        $lenx = unpack(‘v*’, $this->_read_head_buf(10));
        for ($i = 1; $i <= count($this->items1); $i++)
        {
          $k = $this->items1[$i-1];
          $ret[$k] = dbcs_gbk($this->_read_head_buf($lenx[$i]));
        }
      }
      else if ($tmp[‘id’] == ’40a4d0d207e3d21197f000a0c95ea850′)
      {  // Extended Info
        $inum = $this->_read_head_short();
        $tmp[‘len’] -= 26;
        while ($inum > 0 && $tmp[‘len’] > 0)
        {
          // attribute name
          $nlen = $this->_read_head_short();
          $nbuf = $this->_read_head_buf($nlen);
          // the flag & value  length
          $flag = $this->_read_head_short();
          $vlen = $this->_read_head_short();
          $vbuf = $this->_read_head_buf($vlen);
          // update the XX
          $tmp[‘len’] -= (6 + $nlen + $vlen);
          $inum–;
          $name = dbcs_gbk($nbuf);
          $k = substr($name, 3);
          if (in_array($k, $this->items2))
          {  // all is string value (refer to falg for other tags)
            $ret[$k] = dbcs_gbk($vbuf);
          }
        } 
      }
      else
      {  // skip only
        if ($tmp[‘len’] > 24) $this->head_off += ($tmp[‘len’] – 24);
      }
    }
    $this->_file_deinit();
    return $ret;
  }
  // get the header?
  function _init_header()
  {
    fseek($this->fd, 0, SEEK_SET);
    $buf = fread($this->fd, 30);
    if (strlen($buf) != 30) return false;
    $tmp = unpack(‘H32id/Vlen/Vlen2/Vnum/H4unused’, $buf);
    if ($tmp[‘id’] != ‘3026b2758e66cf11a6d900aa0062ce6c’)
      return false;
    $this->head_buf = fread($this->fd, $tmp[‘len’] – 30);
    $this->head = $tmp;
    return true;
  }
  // _get_head_frame()
  function _get_head_frame()
  {
    $buf = $this->_read_head_buf(24); 
    if (strlen($buf) != 24) return false;
    $tmp = unpack(‘H32id/Vlen/H8unused’, $buf);
    return $tmp;
  }
}
// mp3 class (if not IDv2 then select IDv1)
class _Mp3Exif extends _AudioExif
{
  var $head1;
  var $genres = array(‘Blues’,’Classic Rock’,’Country’,’Dance’,’Disco’,’Funk’,’Grunge’,’Hip-Hop’,’Jazz’,’Metal’,’New Age’,’Oldies’,’Other’,’Pop’,’R&B’,’Rap’,’Reggae’,’Rock’,’Techno’,’Industrial’,’Alternative’,’Ska’,’Death Metal’,’Pranks’,’Soundtrack’,’Euro-Techno’,’Ambient’,’Trip-Hop’,’Vocal’,’Jazz+Funk’,’Fusion’,’Trance’,’Classical’,’Instrumental’,’Acid’,’House’,’Game’,’Sound Clip’,’Gospel’,’Noise’,’AlternRock’,’Bass’,’Soul’,’Punk’,’Space’,’Meditative’,’Instrumental Pop’,’Instrumental Rock’,’Ethnic’,’Gothic’,’Darkwave’,’Techno-Industrial’,’Electronic’,’Pop-Folk’,’Eurodance’,’Dream’,’Southern Rock’,’Comedy’,’Cult’,’Gangsta’,’Top 40′,’Christian Rap’,’Pop/Funk’,’Jungle’,’Native American’,’Cabaret’,’New Wave’,’Psychadelic’,’Rave’,’Showtunes’,’Trailer’,’Lo-Fi’,’Tribal’,’Acid Punk’,’Acid Jazz’,’Polka’,’Retro’,’Musical’,’Rock & Roll’,’Hard Rock’,’Unknown’);
  // MP3 always return true
  function check_size($file)
  {
    return true;
  }
  // get info
  function get_info($file)
  {
    if (!$this->_file_init($file)) return false; 
    $ret = false;
    if ($this->_init_header())
    {
      $ret = ($this->head ? $this->_get_v2_info() : $this->_get_v1_info());
      $ret[‘meta’] = $this->_get_meta_info();
    }
    $this->_file_deinit();
    return $ret;
  }
  // set info
  function set_info($file, $pa)
  {
    if (!$this->_file_init($file, true)) return false;
    if ($this->_init_header())
    {
      // always save v1 info
      $this->_set_v1_info($pa);    
      // set v2 first if need
      $this->_set_v2_info($pa);
    }
    $this->_file_deinit();
    return true;
  }
  // get the header information[v1+v2], call after file_init
  function _init_header()
  {
    $this->head1 = false;
    $this->head = false;
    // try to get ID3v1 first
    fseek($this->fd, -128, SEEK_END);
    $buf = fread($this->fd, 128);
    if (strlen($buf) == 128 && substr($buf, 0, 3) == ‘TAG’)
    {
      $tmp = unpack(‘a3id/a30Title/a30Artist/a30AlbumTitle/a4Year/a28Description/CReserved/CTrack/CGenre’, $buf);
      $this->head1 = $tmp;    
    }
    // try to get ID3v2
    fseek($this->fd, 0, SEEK_SET);
    $buf = fread($this->fd, 10);
    if (strlen($buf) == 10 && substr($buf, 0, 3) == ‘ID3’)
    {
      $tmp = unpack(‘a3id/Cver/Crev/Cflag/C4size’, $buf);
      $tmp[‘size’] = ($tmp[‘size1’]<<21)|($tmp[‘size2’]<<14)|($tmp[‘size3’]<<7)|$tmp[‘size4’];
      unset($tmp[‘size1’], $tmp[‘size2’], $tmp[‘size3’], $tmp[‘size4’]);
      $this->head = $tmp;
      $this->head_buf = fread($this->fd, $tmp[‘size’]);
    }
    return ($this->head1 || $this->head);
  }
  // get v1 info
  function _get_v1_info()
  {
    $ret = array();
    $tmpa = array(‘Title’, ‘Artist’, ‘Copyright’, ‘Description’, ‘Year’, ‘AlbumTitle’);
    foreach ($tmpa as $tmp)
    {    
      $ret[$tmp] = $this->head1[$tmp];
      if ($pos = strpos($ret[$tmp], “”))
        $ret[$tmp] = substr($ret[$tmp], 0, $pos);
    }
    // count the Genre, [Track]
    if ($this->head1[‘Reserved’] == 0) $ret[‘Track’] = $this->head1[‘Track’];
    else $ret[‘Description’] .= chr($ret[‘Reserved’]) . chr($ret[‘Track’]);
    // Genre_idx
    $g = $this->head1[‘Genre’];
    if (!isset($this->genres[$g])) $ret[‘Genre’] = ‘Unknown’;
    else $ret[‘Genre’] = $this->genres[$g];
    // return the value
    $ret[‘ID3v1’] = ‘yes’;
    return $ret;
  }
  // get v2 info
  function _get_v2_info()
  {
    $ret = array();
    $items = array(  ‘TCOP’=>’Copyright’, ‘TPE1’=>’Artist’, ‘TIT2’=>’Title’, ‘TRCK’=> ‘Track’,
            ‘TCON’=>’Genre’, ‘COMM’=>’Description’, ‘TYER’=>’Year’, ‘TALB’=>’AlbumTitle’);
    while (true)
    {
      $buf = $this->_read_head_buf(10);
      if (strlen($buf) != 10) break;    
      $tmp = unpack(‘a4fid/Nsize/nflag’, $buf);
      if ($tmp[‘size’] == 0) break;
      $tmp[‘dat’] = $this->_read_head_buf($tmp[‘size’]);
      // 0x6000 (11000000 00000000) 
      if ($tmp[‘flag’] & 0x6000) continue;
      // mapping the data
      if ($k = $items[$tmp[‘fid’]])
      {  // If first char is “”, just skip
        if (substr($tmp[‘dat’], 0, 1) == “”) $tmp[‘dat’] = substr($tmp[‘dat’], 1);
        $ret[$k] = $tmp[‘dat’];
      }
    }
    // reset the genre
    if ($g = $ret[‘Genre’])
    {
      if (substr($g,0,1) == ‘(‘ && substr($g,-1,1) == ‘)’) $g = substr($g, 1, -1);
      if (is_numeric($g))
      {
        $g = intval($g);
        $ret[‘Genre’] = (isset($this->genres[$g]) ? $this->genres[$g] : ‘Unknown’);
      }
    }
    $ret[‘ID3v1’] = ‘no’;
    return $ret;
  }
  // get meta info of MP3
  function _get_meta_info()
  {
    // seek to the lead buf: 0xff
    $off = 0;
    if ($this->head) $off = $this->head[‘size’] + 10;
    fseek($this->fd, $off, SEEK_SET);
    while (!feof($this->fd))
    {
      $skip = ord(fread($this->fd, 1));
      if ($skip == 0xff) break;
    }
    if ($skip != 0xff) return false;
    $buf = fread($this->fd, 3);
    if (strlen($buf) != 3) return false;
    $tmp = unpack(‘C3’, $buf);
    if (($tmp[1] & 0xf0) != 0xf0) return false;
    // get the meta info
    $meta = array();
    // get mpeg version
    $meta[‘mpeg’]  = ($tmp[1] & 0x08 ? 1 : 2);
    $meta[‘layer’]  = ($tmp[1] & 0x04) ? (($tmp[1] & 0x02) ? 1 : 2) : (($tmp[1] & 0x02) ? 3 : 0);
    $meta[‘epro’]  = ($tmp[1] & 0x01) ? ‘no’ : ‘yes’;
    // bit rates
    $bit_rates = array(
      1 => array(
        1 => array(0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0),
        2 => array(0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0),
        3 => array(0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0)
      ),
      2 => array(
        1 => array(0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0),
        2 => array(0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0),
        3 => array(0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0)
      )
    );
    $i = $meta[‘mpeg’];
    $j = $meta[‘layer’];
    $k = ($tmp[2]>>4);
    $meta[‘bitrate’] = $bit_rates[$i][$j][$k];
// Sample Rates <Singlement rate>
    $sam_rates = array(1=>array(44100,48000,32000,0), 2=>array(22050,24000,16000,0));
    $meta[‘samrate’] = $sam_rates[$i][$k];
    $meta[“padding”] = ($tmp[2] & 0x02) ? ‘on’ : ‘off’;
    $meta[“private”] = ($tmp[2] & 0x01) ? ‘on’ : ‘off’;
    // mode & mode_ext
    $k = ($tmp[3]>>6);
    $channel_modes = array(‘stereo’, ‘joint stereo’, ‘dual channel’, ‘single channel’);
    $meta[‘mode’] = $channel_modes[$k];
    $k = (($tmp[3]>>4) & 0x03);
    $extend_modes = array(‘MPG_MD_LR_LR’, ‘MPG_MD_LR_I’, ‘MPG_MD_MS_LR’, ‘MPG_MD_MS_I’);
    $meta[‘ext_mode’] = $extend_modes[$k];
    $meta[‘copyright’] = ($tmp[3] & 0x08) ? ‘yes’ : ‘no’;
    $meta[‘original’] = ($tmp[3] & 0x04) ? ‘yes’ : ‘no’;
    $emphasis = array(‘none’, ’50/15 microsecs’, ‘rreserved’, ‘CCITT J 17’);
    $k = ($tmp[3] & 0x03);
    $meta[’emphasis’] = $emphasis[$k];
    return $meta;
  }
  // set v1 info
  function _set_v1_info($pa)
  {
    // ID3v1 (simpled)
    $off = -128;
    if (!($tmp = $this->head1))
    {    
      $off = 0;
      $tmp[‘id’] = ‘TAG’;
      $tmp[‘Title’] = $tmp[‘Artist’] = $tmp[‘AlbumTitle’] = $tmp[‘Year’] = $tmp[‘Description’] = ”;
      $tmp[‘Reserved’] = $tmp[‘Track’] = $tmp[‘Genre’] = 0;
    }

    // basic items
    $items = array(‘Title’, ‘Artist’, ‘Copyright’, ‘Description’, ‘Year’, ‘AlbumTitle’);
    foreach ($items as $k)
    {
      if (isset($pa[$k])) $tmp[$k] = $pa[$k];
    }
    // genre index
    if (isset($pa[‘Genre’]))
    {
      $g = 0;
      foreach ($this->genres as $gtmp)
      {
        if (!strcasecmp($gtmp, $pa[‘Genre’]))
          break;
        $g++;
      }
      $tmp[‘Genre’] = $g;
    }
    if (isset($pa[‘Track’])) $tmp[‘Track’] = intval($pa[‘Track’]);
    // pack the data
    $buf = pack(‘a3a30a30a30a4a28CCC’,  $tmp[‘id’], $tmp[‘Title’], $tmp[‘Artist’], $tmp[‘AlbumTitle’],
            $tmp[‘Year’], $tmp[‘Description’], 0, $tmp[‘Track’], $tmp[‘Genre’]);
    flock($this->fd, LOCK_EX);
    fseek($this->fd, $off, SEEK_END);
    fwrite($this->fd, $buf, 128);
    flock($this->fd, LOCK_UN);
  }
  // set v2 info
  function _set_v2_info($pa)
  {
    if (!$this->head)
    {  // insert ID3
Return; //
      /**
      $tmp = array(‘id’=>’ID3’,’ver’=>3,’rev’=>0,’flag’=>0);
      $tmp[‘size’] = -10;  // +10 => 0
      $this->head = $tmp;
      $this->head_buf = ”;
      $this->head_off = 0;
      **/
    }
    $items = array(  ‘TCOP’=>’Copyright’, ‘TPE1’=>’Artist’, ‘TIT2’=>’Title’, ‘TRAC’=>’Track’,
            ‘TCON’=>’Genre’, ‘COMM’=>’Description’, ‘TYER’=>’Year’, ‘TALB’=>’AlbumTitle’);
    $head_body = ”;
    while (true)
    {
      $buf = $this->_read_head_buf(10);
      if (strlen($buf) != 10) break;
      $tmp = unpack(‘a4fid/Nsize/nflag’, $buf);
      if ($tmp[‘size’] == 0) break;
      $data = $this->_read_head_buf($tmp[‘size’]);
      if (($k = $items[$tmp[‘fid’]]) && isset($pa[$k]))
      {
        // the data should prefix by “” [replace]
        $data = “” . $pa[$k];
        unset($pa[$k]);
      }
      $head_body .= pack(‘a4Nn’, $tmp[‘fid’], strlen($data), $tmp[‘flag’]) . $data;
    }
    // reverse the items & set the new tags
    $items = array_flip($items);
    foreach ($pa as $k => $v)
    {
      if ($fid = $items[$k])
      {
        $head_body .= pack(‘a4Nn’, $fid, strlen($v) + 1, 0) . “” . $v;
      }
    }
    // new length
    $new_len = strlen($head_body) + 10;
    $old_len = $this->head[‘size’] + 10;
    if ($new_len < $old_len)
    {
      $head_body .= str_repeat(“”, $old_len – $new_len);
      $new_len = $old_len;    
    }
    // count the size1,2,3,4, no include the header
// More abnormal algorithms …: P (28bytes Integer)
    $size = array();
    $nlen = $new_len – 10;
    for ($i = 4; $i > 0; $i–)
    {
      $size[$i] = ($nlen & 0x7f);
      $nlen >>= 7;
    }
    $tmp = $this->head;
    //echo “old_len : $old_len new_len: $new_len “;
    $head_buf = pack(‘a3CCCCCCC’, $tmp[‘id’], $tmp[‘ver’], $tmp[‘rev’], $tmp[‘flag’],
      $size[1], $size[2], $size[3], $size[4]);
    $head_buf .= $head_body;
    $this->_file_save($head_buf, $old_len, $new_len);
  }
}
?>