月度归档:2013年10月

10个最热JavaScript开源框架的社区活跃度对比

每个开源项目都会有属于自己的社区,社区的活跃程度也间接反应了该项目的活跃程度如何。本文挑选了目前最火的10个JavaScript开源框架,不妨来看看哪个是最活跃的项目。

社区能力也是决定JavaScript框架能否被开发者采纳的一个巨大因素。当考虑一个框架是否满足项目需要时,开发者需要考虑哪些因素呢?本文将深入调查活跃度最高的10个JavaScript框架。本文数据来自Ohloh.netGitHub

在过去几年,大量的UI库和框架涌现在开发者们面前,并且大多数都是开源的,关于它们的使用情况以及完整性,网上都有所描述。但人们在选择时,往往忽视了一些指标,比如强度、社区能力以及围绕该开源项目的整个生态系统,殊不知,这些指标都扮演着非常重要的角色。

Top 10项目

我们根据以上因素,深入社区挖掘出了当今热门的Top 10开源JavaScript框架,这些框架类型涉及到UI库、全栈框架等。这些热门的项目分别是:

 

  1. AngularJS
  2. Ember.js
  3. SproutCore
  4. Backbone.JS
  5. Knockout.js
  6. SpineJS
  7. CanJS
  8. Meteor.JS
  9. Derby.js
  10. Yahoo Mojito

 

我们会对这10个项目的社区规模、增长情况以及围绕该项目的整个生态系统项目进行统计。

月代码贡献量

下面这个图表反映了每个项目,每个月所有参与者的代码贡献量,这也可以直接反映出项目的活跃度。

从上图可以看出,Ember.js和Google的AngularJS的贡献量增长最快,而作为早期的领跑者SproutCore,从2011年12月开始,贡献量呈明显下降趋势。除了Ember.js和AngularJS,Backbone.JS和MeteorJS的贡献量也不容小觑。

参与项目的贡献者

统计项目一直以来的贡献者人数,也可以反映出许多问题,比如该项目的治理风格,许多项目都是由一些较小的团队来打理;当然,贡献者越多,问题修复速度就越快,文档可能越全面。

从上图可以看出,AngularJS和Ember.js的贡献人数是最多的,并且近期增长速度也相当快速。

 

项目的生态系统 

 

除了贡献者,基于该库所建立的项目以及项目拓展的整个生态系统也是社区力量显而易见的体现。这也表明,一个核心的项目并不总是独立的,拥有广泛的生态系统也是一个项目成功的关键。

一个开源项目的健壮性在一定程度的可以从它周围的项目来衡量。毫无疑问,Backbone.JS拥有非常庞大的生态系统,在整个行业中的使用范围也非常广泛。

全栈解决方案

因为全栈解决方案的适用范围可能与其他项目不同,所以我们对其进行了单独的研究。全栈解决方案包括一个客户端框架和服务器端框架;所涉及的代码量应该更大,随着时间推移,参与的贡献人数也会增加。

JavaScript的崛起

越来越多的开发者愿意投入时间和创建结构化方法来使用JavaScript,下图显示了自2011年初,使用该10大框架的开发者增长数。并且也说明了JavaScript正在试图吞并世界,2013年的平均数量几乎是2011年的两倍。

提交的代码行数

图中可以看出,所有参与项目的贡献者与所提交的行数存在一定的差别,这表明这些项目更易于开发者做出贡献,并且可以进行长期可持续发展。

社区规模和贡献者增长数量是一个非常重要的项目指标。虽然这些指标不能告诉我们整个故事,但对开发者来说,这些数据给他们提供了很好的说明,并且可以反映目前项目的投资情况以及基于其可行性和可持续性,帮助开发者做出一些决策,帮助开发者找到整个项目周期的临界点。

来自:InfoWorld

Web设计师和Web开发者之间的区别是什么?

Web设计师和Web开发者的概念难以分清楚。一个是有关网站的视觉或美学方面,被称为“前端”;另一个则是看不见的编码方面设计,被称为“后端”。那么,这两者之间有什么区别与联系呢?谁才是真实的设计师或开发者呢?

在日常工作中,你几乎在哪都能听到有人在讨论或者称自己是一名Web设计师或是Web开发者。那么,这两者之间有什么区别呢?谁才是真实的设计师或是开发者呢?

通常我们对Web设计师和Web开发者的概念分不清楚,两者之间既有区别又有联系。最大的差异是: 一个是有关网站的视觉或美学方面,被称为“前端”;另一个则是看不见的编码方面的设计,被称为“后端”。简而言之,漂亮的网站界面都是出自网页设计师之手,而牛逼强大的功能则是网页开发者的杰作。原文作者Carrie Cousins详细阐述了两者之间的区别与联系。我们一起来看下:

设计师的工作


首先,值得肯定的一点是,每种工作都有它存在的价值。

通常,Web设计师主要处理可视化布局的网站。他们通过使用图形和图形设计软件(Adobe Photoshop,Illustrator 和InDesign等)来创建可视化的Web网页,一旦完成后再由Web开发人员进行编码。

不是每个设计师都是懂编码的,但在某些情况下,有些工作团队能够独立完成网站设计。优秀的设计师在各种概念使用上运用自如,比如色彩的搭配、排版、空间关系以及用户体验等。

开发者的工作


虽然Web开发者的工作内容与设计师的相似,但是它们两者之间也存在不同之处。

Web开发者通常是负责网站的后端开发,这就要求他们掌握特定的Web语言。比如HTML、Javascript、JQuery 以及CSS。一般情况下,Web开发者不会注重视觉上的东西,但他们却很在意洁净的代码。

Web开发者通常被认为是使用左脑开发的人群。从技能角度上讲,技术能力和思维逻辑是必不可少的一部分。Web开发涉及到各个领域,包括计算机科学或编程。大多数公司需要这种组合技能。优秀的开发者通常会注重细节,并且关注每一处细节。

两种工作,同一个目标

无论是Web设计师还是Web开发者,他们都朝着同一个目标而努力——创建一款能吸引更多用户的网站或应用。

要做到这一点,设计和开发的出发点需要一致。一个优秀的网站应看着美观且运行良好。色彩和图形能够凸现名牌意识;界面能激发游客采取行动。

如今,设计师与开发者之间的界限越来越模糊,这是因为越来越多的设计师开始学习编码,开发者也开始密切关注设计理论。(这也是为什么有关设计和开发方面的教程如此受欢迎的原因之一)。

一起工作


设计师与开发者之间最难逾越的一条鸿沟便是两者在一起工作以及交流方式。当遇到问题时,双方各有各的偏词,之前我们也曾发过一篇《开发者和设计师,为何我们不能好好相处》。

下面这些技巧,能够帮助消除沟通障碍:

 

  • 避免使用行话。
  • 不要直接告诉对方应该如何看或者如何操作。如果你不知道如何解释,那么在会议上用草图或案例进行阐述。
  • 思想开放。设计师应当接受开发者的设计理念,开发者也应该积极接受设计师对用户体验方面的反馈意见。
  • 学习其他网站的创建过程。阅读你所不知道的内容并积极提问。

 

你会成为设计师兼开发者吗?

所有的这些差异似乎意味着,设计师和开发者是两种不同的工作或角色。

但是,事实并非如此。

当然,你也可以同时成为设计师兼开发者。越来越多的人们开始以这种方式来标榜自己,并且这种技能组合也逐渐变得炙手可热。设计和开发领域覆盖了大部分人群,可惜,有的设计师从未想过学习开发方面的知识;反之,开发者也亦如此。

原文出自:Designmodo 

12 个实用的Chrome命令

许多实用的功能并没有直接显示在Chrome的菜单上。你可以通过chrome:// command使用这些功能。在这篇文章中,我们将介绍12个实用的chrome:// commands。

1. chrome://flags

它可以用来打开或关闭一些chrome特性。

2. chrome://dns

此命令将显示浏览器捕捉到的域名列表。

3. chrome://downloads

下载管理界面,可以从菜单访问。其快捷键是Ctrl+J。

4. chrome://extensions

这个命令相当于Menu->Tools->Extensions

5. chrome://bookmarks

这个命令相当于Menu->Bookmarks->Bookmark管理器。其快捷键是Ctrl+Shift+O

6. chrome://history

这个命令相当于Menu->History. 其快捷键是 Ctrl+H.

7. chrome://memory

此命令将重定向到“chrome://memory-redirect/”。它会显示浏览器的内存使用状态和运行在系统中其它的浏览器包括Firefox。它也可以显示浏览器的进程。

8. chrome://net-internals

这个命令将显示浏览器的网络信息和网络事件。可以导出数据和DNS缓存。

其中一个重要的功能是检测,如果你不能访问某些 URL,你可以打开“chrome://net-internals” -> 点击 “Tests” tab->输入URL测试。Chrome将报告错误信息。

9. chrome://quota-internals

这个命令将浏览器的硬盘空间使用状态。

10. chrome://sessions

这个命令将显示对话信息。

11.  chrome://settings

这个命令也可以通过Menu->Options调用。可以在此配置浏览器的所有设置。

12. chrome://sync-internals

这个命令将显示Chrome的同步状态。

F

最后你可以使用 chrome://about/ 来查看所有 chrome:// commands的相关信息

PHP错误日志

对于PHP开发者来说,一旦某个产品投入使用,应该立即将display_errors选项关闭,以免因为这些错误所透露的路径、数据库连接、数据表等信息而遭到黑客攻击。但是,任何一个产品在投入使用后,都难免会有错误出现,那么如何记录一些对开发者有用的错误报告呢?我们可以在单独的文本文件中将错误报告作为日志记录。错误日志的记录,可以帮助开发人员或者管理人员查看系统是否存在问题。 如果需要将程序中的错误报告写入错误日志中,只要在PHP的配置文件中,将配置指令log_errors开启即可。错误报告默认就会记录到Web服务器的日志文件里,例如记录到Apache服务器的错误日志文件error.log中。当然也可以记录错误日志到指定的文件中或发送给系统syslog,分别介绍如下:

1、使用指定的文件记录错误报告日志

使用指定的文件记录错误报告日志使用指定的文件记录错误报告日志使用指定的文件记录错误报告日志 如果使用自己指定的文件记录错误日志,一定要确保将这个文件存放在文档根目录之外,以减少遭到攻击的可能。并且该文件一定要让PHP脚本的执行用户(Web服务器进程所有者)具有写权限。假设在Linux操作系统中,将/usr/local/目录下的error.log文件作为错误日志文件,并设置Web服务器进程用户具有写的权限。然后在PHP的配置文件中,将error_log指令的值设置为这个错误日志文件的绝对路径。

 

需要将php.ini中的配置指令做如下修改:

1. error_reporting  =  E_ALL                   ;将会向PHP报告发生的每个错误

2. display_errors = Off                        ;不显示满足上条 指令所定义规则的所有错误报告

3. log_errors = On                             ;决定日志语句记录的位置

4. log_errors_max_len = 1024                   ;设置每个日志项的最大长度

5. error_log = /usr/local/error.log                ;指定产生的 错误报告写入的日志文件位置

 

PHP的配置文件按上面的方式设置完成以后,并重新启动Web服务器。这样,在执行PHP的任何脚本文件时,所产生的所有错误报告都不会在浏览器中显示,而会记录在自己指定的错误日志/usr/local/error.log中。此外,不仅可以记录满足error_reporting所定义规则的所有错误,而且还可以使用PHP中的error_log()函数,送出一个用户自定义的错误信息。

该函数的原型如下所示:

1. bool error_log ( string message [, int message_type  [, string destination [, string extra_headers]]] )

此函数会送出错误信息到Web服务器的错误日志文件、某个TCP服务器或到指定文件中。该函数执行成功则返回TRUE,失败则返回FALSE。第一个参数message 是必选项,即为要送出的错误信息。如果仅使用这一个参数,会按配置文件php.ini中所设置的位置处发送消息。第二个参数message_type为整数值:0表示送到操作系统的日志中;1则使用PHP的Mail()函数,发送信息到某E-mail处,第四个参数extra_headers亦会用到;2则将错误信息送到TCP 服务器中,此时第三个参数destination表示目的地IP及Port;3则将信息存到文件destination中。

如果以登入Oracle数据库出现问题的处理为例,该函数的使用如下所示:

1. <?php

2.     if(!Ora_Logon($username, $password)){

3.         error_log(“Oracle数据库不可用!”, 0);        //将错误消息写入到操作系统日志中

4.     }

5.     if(!($foo=allocate_new_foo()){

6.         error_log(“出现大麻烦了!”, 1, “. mydomain.com”);   //发送到管理员邮箱中

7.     }

8.     error_log(“搞砸了!”,   2,   “localhost:5000”);     //发送到本机对应5000端口的服务器中

9.     error_log(“搞砸了!”,   3,   “/usr/local/errors.log”);  //发送到指定的文件中

10. ?>

 

2、 错误信息记录到操作系统的日志里

错误信息记录到操作系统的日志里错误信息记录到操作系统的日志里错误信息记录到操作系统的日志里 错误报告也可以被记录到操作系统日志里,但不同的操作系统之间的日志管理有点区别。在Linux上错误语句将送往syslog,而在Windows上错误将发送到事件日志里。如果你不熟悉syslog,起码要知道它是基于UNIX的日志工具,它提供了一个API来记录与系统和应用程序执行有关的消息。Windows事件日志实际上与UNIX的syslog相同,这些日志通常可以通过事件查看器来查看。如果希望将错误报告写到操作系统的日志里,可以在配置文件中将error_log指令的值设置为syslog。

具体需要在php.ini中修改的配置指令如下所示:

1. error_reporting  =  E_ALL                   ;将会向PHP报告发生的每个错误

2. display_errors = Off                            ;不显示 满足上条指令所定义规则的所有错误报告

3. log_errors = On                             ;决定日志语句记录的位置

4. log_errors_max_len = 1024                   ;设置每个日志项的最大长度

5. error_log = syslog                          ;指定产生的错误报告写入操作系统的日志里

 

除了一般的错误输出之外,PHP还允许向系统syslog中发送定制的消息。虽然通过前面介绍的error_log()函数,也可以向syslog中发送定制的消息,但在PHP中为这个特性提供了需要一起使用的4个专用函数。

分别介绍如下:

define_syslog_variables() 

在使用openlog()、syslog及closelog()三个函数之前必须先调用该函数。因为在调用该函数时,它会根据现在的系统环境为下面三个函数初使用化一些必需的常量。

openlog() 

打开一个和当前系统中日志器的连接,为向系统插入日志消息做好准备。并将提供的第一个字符串参数插入到每个日志消息中,该函数还需要指定两个将在日志上下文使用的参数,可以参考官方文档使用。

 syslog()

该函数向系统日志中发送一个定制消息。需要两个必选参数,第一个参数通过指定一个常量定制消息的优先级。例如LOG_WARNING表示一般的警告,LOG_EMERG表示严重地可以预示着系统崩溃的问题,一些其他的表示严重程度的常量可以参考官方文档使用。第二个参数则是向系统日志中发送的定制消息,需要提供一个消息字符串,也可以是PHP引擎在运行时提供的错误字符串。

closelog()

该函数在向系统日志中发送完成定制消息以后调用,关闭由openlog()函数打开的日志连接。

 

如果在配置文件中,已经开启向syslog发送定制消息的指令,就可以使用前面介绍的四个函数发送一个警告消息到系统日志中,并通过系统中的syslog解析工具,查看和分析由PHP程序发送的定制消息,如下所示:

1.

2.     define_syslog_variables();

3.     openlog(“PHP5”, LOG_PID , LOG_USER);

4.     syslog(LOG_WARNING, “警告报告向syslog中发送的演示, 警告时间:”.date(“Y/m/d H:i:s”));

5.     closelog();

6. ?>

以Windows系统为例,通过右击”我的电脑”选择管理选项,然后到系统工具菜单中,选择事件查看器,再找到应用程序选项,就可以看到我们自己定制的警告消息了。上面这段代码将在系统的syslog文件中,生成类似下面的一条信息,是事件的一部分:

1. PHP5[3084], 警告报告向syslog中发送的演示, 警告时间:2009/03/26 04:09:11.

使用指定的文件还是使用syslog记录错误日志,取决于你所在的Web服务器环境。如果你可以控制Web服务器,使用syslog是最理想的,因为你能利用syslog的解析工具来查看和分析日志。但如果你的网站在共享服务器的虚拟主机中运行,就只有使用单独的文本文件记录错误日志了。

我可以在Google App Engine跑PHP了,今天才知道

不记得什么时候申请Google App Engine了,只知道它GAE有PHP后我就去申请了,竟然在9月27日审核通过白名单,也许和正式发布有关系吧,但真心的说GAE非常稳定,打算有空的时候发布一个测试版的Upcms!

以下是通过邮件,要是你也是PHPER同时也在关注GAE,我个人关注GAE是因为我对GC毕竟感兴趣,其中的API调用都是在GAE上运行的,哈哈!!

Congratulations!

We just wanted to let you know that your App Engine account:
v3u3i87@gmail.com
has been successfully whitelisted to deploy PHP applications.

This means you can now deploy projects that use the PHP runtime to
any App Engine application for which this account is a developer.

While we’re in Preview you can keep up to date with the latest news on
Google App Engine for PHP by joining our Google+ community:
http://goo.gl/YZ6HGs

You can also read our online documentation:
https://developers.google.com/appengine/docs/php/gettingstarted/
https://developers.google.com/appengine/docs/php/

If you’re setting up a WordPress blog, don’t forget our tutorial:
https://developers.google.com/appengine/articles/wordpress

You can get help from other App Engine developers on Stack Overflow:
http://stackoverflow.com/questions/tagged/google-app-engine+php

And if you find a bug, or would like to request a feature, you can
do so on our Issue Tracker:
https://code.google.com/p/googleappengine/issues/list?q=label:Language-PHP&sort=-stars

Thanks for being one of the first to try Google App Engine for PHP.

Enjoy! We can’t wait to see what you come up with.

– The App Engine Team

Facebook2007年的2份代码,竟然是那么简单的!

抱着学习的心态,细细的全部看完了,代码,虽然一些方法不知道具体处理啥,但思路和写法典型的面向过程,以为那时候那位创始人会是面向对象的,看了很多关于大公司的代码几乎都是面向过程,特别是谷歌的API系列,为啥在面向对象当道的今天在国内都是这样强调的,而在国外竟然会是不同的,值得学习下,过分的class function 也许对各个不同的环节也要启用不同的方法!

此原文来自:https://gist.github.com/nikcub/3833406#file-search-php
In August 2007 a hacker found a way to expose the PHP source code on facebook.com. He retrieved two files and then emailed them to me, and I wrote about the issue:

http://techcrunch.com/2007/08/11/facebook-source-code-leaked/

It became a big deal:

http://www.techmeme.com/070812/p1#a070812p1

The two files are index.php (the homepage) and search.php (the search page)

I don’t know what ended up happening to the guy who stole the code.

I found these files today while searching for another Facebook related file. Worth preserving as part of Internet history.
index.php
 

< ? php include_once $_SERVER['PHP_ROOT'].'/html/init.php'; include_once $_SERVER['PHP_ROOT'].'/lib/home.php'; include_once $_SERVER['PHP_ROOT'].'/lib/requests.php'; include_once $_SERVER['PHP_ROOT'].'/lib/feed/newsfeed.php'; include_once $_SERVER['PHP_ROOT'].'/lib/poke.php'; include_once $_SERVER['PHP_ROOT'].'/lib/share.php'; include_once $_SERVER['PHP_ROOT'].'/lib/orientation.php'; include_once $_SERVER['PHP_ROOT'].'/lib/feed/newsfeed.php'; include_once $_SERVER['PHP_ROOT'].'/lib/mobile/register.php'; include_once $_SERVER['PHP_ROOT'].'/lib/forms_lib.php'; include_once $_SERVER['PHP_ROOT'].'/lib/contact_importer/contact_importer.php'; include_once $_SERVER['PHP_ROOT'].'/lib/feed/util.php'; include_once $_SERVER['PHP_ROOT'].'/lib/hiding_prefs.php'; include_once $_SERVER['PHP_ROOT'].'/lib/abtesting.php'; include_once $_SERVER['PHP_ROOT'].'/lib/friends.php'; include_once $_SERVER['PHP_ROOT'].'/lib/statusupdates.php'; // lib/display/feed.php has to be declared here for scope issues. // This keeps display/feed.php cleaner and easier to understand. include_once $_SERVER['PHP_ROOT'].'/lib/display/feed.php'; include_once $_SERVER['PHP_ROOT'].'/lib/monetization_box.php'; // require login $user = require_login(); print_time('require_login'); param_request(array('react' = > $PARAM_EXISTS));

// Check and fix broken emails
// LN - disabling due to excessive can_see dirties and sets when enabled.
//check_and_fix_broken_emails($user);
// migrate AIM screenname from profile to screenname table if needed
migrate_screenname($user);

// homepage announcement variables
$HIDE_ANNOUNCEMENT_BIT = get_site_variable('HIDE_ANNOUNCEMENT_BIT');
$HIDE_INTRO_BITMASK = get_site_variable('HIDE_INTRO_BITMASK');

// redirects
if (is_sponsor_user()) {
redirect('bizhome.php', 'www');
}

include_once $_SERVER['PHP_ROOT'].'/lib/mesg.php';
include_once $_SERVER['PHP_ROOT'].'/lib/invitetool.php';
include_once $_SERVER['PHP_ROOT'].'/lib/grammar.php';
include_once $_SERVER['PHP_ROOT'].'/lib/securityq.php';
include_once $_SERVER['PHP_ROOT'].'/lib/events.php';
include_once $_SERVER['PHP_ROOT'].'/lib/rooster/stories.php';

// todo: password confirmation redirects here (from html/reset.php),
// do we want a confirmation message?
param_get_slashed(array(
'feeduser' = > $PARAM_INT, //debug: gets feed for user here
'err' = > $PARAM_STRING, // returning from a failed entry on an orientation form
'error' = > $PARAM_STRING, // an error can also be here because the profile photo upload code is crazy
'ret' = > $PARAM_INT, 'success' = > $PARAM_INT, // successful profile picture upload
'jn' = > $PARAM_INT, // joined a network for orientation
'np' = > $PARAM_INT, // network pending (for work/address network)
'me' = > $PARAM_STRING, // mobile error
'mr' = > $PARAM_EXISTS, // force mobile reg view
'mobile' = > $PARAM_EXISTS, // mobile confirmation code sent
'jif' = > $PARAM_EXISTS, // just imported friends
'ied' = > $PARAM_STRING, // import email domain
'o' = > $PARAM_EXISTS, // first time orientation, passed on confirm
'verified' = > $PARAM_EXISTS)); // verified mobile phone

param_post(array(
'leave_orientation' = > $PARAM_EXISTS,
'show_orientation' = > $PARAM_INT, // show an orientation step
'hide_orientation' = > $PARAM_INT)); // skip an orientation step

// homepage actions
if ($req_react && validate_expiring_hash($req_react, $GLOBALS['url_md5key'])) {
$show_reactivated_message = true;
} else {
$show_reactivated_message = false;
}
tpl_set('show_reactivated_message', $show_reactivated_message);

// upcoming events
events_check_future_events($user); // make sure big tunas haven't moved around
$upcoming_events = events_get_imminent_for_user($user);

// this is all stuff that can be fetched together!
$upcoming_events_short = array();
obj_multiget_short(array_keys($upcoming_events), true, $upcoming_events_short);
$new_pokes = 0;

//only get the next N pokes for display
//where N is set in the dbget to avoid caching issues
$poke_stats = get_num_pokes($user);
get_next_pokes($user, true, $new_pokes);
$poke_count = $poke_stats['unseen'];

$targeted_data = array();
home_get_cache_targeted_data($user, true, $targeted_data);
$announcement_data = array();
home_get_cache_announcement_data($user, true, $announcement_data);
$orientation = 0;
orientation_get_status($user, true, $orientation);
$short_profile = array();
profile_get_short($user, true, $short_profile);

// pure priming stuff
privacy_get_network_settings($user, true);
$presence = array();
mobile_get_presence_data($user, true, $presence);
feedback_get_event_weights($user, true);

// Determine if we want to display the feed intro message
$intro_settings = 0;
user_get_hide_intro_bitmask($user, true, $intro_settings);
$user_friend_finder = true;
contact_importer_get_used_friend_finder($user, true, $used_friend_finder);
$all_requests = requests_get_cache_data($user);

// FIXME?: is it sub-optimal to call this both in requests_get_cache_data and here?
$friends_status = statusupdates_get_recent($user, null, 3);
memcache_dispatch(); // populate cache data

// Merman's Admin profile always links to the Merman's home
if (user_has_obj_attached($user)) {
redirect('mhome.php', 'www');
}

if (is_array($upcoming_events)) {
foreach($upcoming_events as $event_id = > $data) {
$upcoming_events[$event_id]['name'] = txt_set($upcoming_events_short[$event_id]['name']);
}
}

tpl_set('upcoming_events', $upcoming_events);

// disabled account actions
$disabled_warning = ((IS_DEV_SITE || IS_QA_SITE) && is_disabled_user($user));
tpl_set('disabled_warning', $disabled_warning);

// new pokes (no more messages here, they are in the top nav!)
if (!user_is_guest($user)) {
tpl_set('poke_count', $poke_count);
tpl_set('pokes', $new_pokes);
}

// get announcement computations
tpl_set('targeted_data', $targeted_data);
tpl_set('announcement_data', $announcement_data);

// birthday notifications
tpl_set('birthdays', $birthdays = user_get_birthday_notifications($user, $short_profile));
tpl_set('show_birthdays', $show_birthdays = (count($birthdays) || !$orientation));

// user info
tpl_set('first_name', user_get_first_name(txt_set($short_profile['id'])));
tpl_set('user', $user);

// decide if there are now any requests to show
$show_requests = false;
foreach($all_requests as $request_category) {
if ($request_category) {
$show_requests = true;
break;
}
}
tpl_set('all_requests', $show_requests ? $all_requests : null);

$permissions = privacy_get_reduced_network_permissions($user, $user);

// status
$user_info = array('user' = > $user, 'firstname' = > user_get_first_name($user), 'see_all' = > '/statusupdates/?ref=hp', 'profile_pic' = > make_profile_image_src_direct($user, 'thumb'), 'square_pic' = > make_profile_image_src_direct($user, 'square'));

if (!empty($presence) && $presence['status_time'] > (time() - 60 * 60 * 24 * 7)) {
$status = array('message' = > txt_set($presence['status']), 'time' = > $presence['status_time'], 'source' = > $presence['status_source']);
} else {
$status = array('message' = > null, 'time' = > null, 'source' = > null);
}
tpl_set('user_info', $user_info);

tpl_set('show_status', $show_status = !$orientation);
tpl_set('status', $status);
tpl_set('status_custom', $status_custom = mobile_get_status_custom($user));
tpl_set('friends_status', $friends_status);

// orientation
if ($orientation) {
if ($post_leave_orientation) {
orientation_update_status($user, $orientation, 2);
notification_notify_exit_orientation($user);
dirty_user($user);
redirect('home.php');
} else if (orientation_eligible_exit(array('uid' = > $user)) == 2) {
orientation_update_status($user, $orientation, 1);
notification_notify_exit_orientation($user);
dirty_user($user);
redirect('home.php');
}
}

// timezone - outside of stealth, update user's timezone if necessary
$set_time = !user_is_alpha($user, 'stealth');
tpl_set('timezone_autoset', $set_time);
if ($set_time) {
$daylight_savings = get_site_variable('DAYLIGHT_SAVINGS_ON');
tpl_set('timezone', $short_profile['timezone'] - ($daylight_savings ? 4 : 5));
}

// set next step if we can
if (!$orientation) {
user_set_next_step($user, $short_profile);
}

// note: don't make this an else with the above statement, because then no news feed stories will be fetched if they're exiting orientation
if ($orientation) {
extract(orientation_get_const());

require_js('js/dynamic_dialog.js');
require_js('js/suggest.js');
require_js('js/typeahead_ns.js');
require_js('js/suggest.js');
require_js('js/editregion.js');
require_js('js/orientation.js');
require_css('css/typeahead.css');
require_css('css/editor.css');

if ($post_hide_orientation && $post_hide_orientation < = $ORIENTATION_MAX) { $orientation['orientation_bitmask'] |= ($post_hide_orientation * $ORIENTATION_SKIPPED_MODIFIER); orientation_update_status($user, $orientation); } else if ($post_show_orientation && $post_show_orientation <= $ORIENTATION_MAX) { $orientation['orientation_bitmask'] &= ~ ($post_show_orientation * $ORIENTATION_SKIPPED_MODIFIER); orientation_update_status($user, $orientation); } $stories = orientation_get_stories($user, $orientation); switch ($get_err) { case $ORIENTATION_ERR_COLLEGE: $temp = array(); // the affil_retval_msg needs some parameters won't be used $stories[$ORIENTATION_NETWORK]['failed_college'] = affil_retval_msg($get_ret, $temp, $temp); break; case $ORIENTATION_ERR_CORP: $temp = array(); // We special case the network not recognized error here, because affil_retval_msg is retarded. $stories[$ORIENTATION_NETWORK]['failed_corp'] = ($get_ret == 70) ? 'The email you entered did not match any of our supported networks. '.'Click here to see our supported list. '.'Go here to suggest your network for the future.' : affil_retval_msg($get_ret, $temp, $temp); break; } // photo upload error if ($get_error) { $stories[$ORIENTATION_ORDER[$ORIENTATION_PROFILE]]['upload_error'] = pic_get_error_text($get_error); } // photo upload success else if ($get_success == 1) { $stories[$ORIENTATION_ORDER[$ORIENTATION_PROFILE]]['uploaded_pic'] = true; // join network success } else if ($get_jn) { $stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]]['joined'] = array('id' = > $get_jn, 'name' = > network_get_name($get_jn));
// network join pending
} else if ($get_np) {

$stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]]['join_pending'] = array('id' = > $get_np, 'email' = > get_affil_email_conf($user, $get_np), 'network' = > network_get_name($get_np));
// just imported friend confirmation
} else if ($get_jif) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]]['just_imported_friends'] = true;
$stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]]['domain'] = $get_ied;
}

// Mobile web API params
if ($get_mobile) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]]['sent_code'] = true;
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]]['view'] = 'confirm';
}
if ($get_verified) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]]['verified'] = true;
}
if ($get_me) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]]['error'] = $get_me;
}
if ($get_mr) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]]['view'] = 'register';
}

if (orientation_eligible_exit($orientation)) {
tpl_set('orientation_show_exit', true);
}
tpl_set('orientation_stories', $stories);

//if in orientation, we hide all feed intros (all 1's in bitmask)
$intro_settings = -1;

}
tpl_set('orientation', $orientation);

// Rooster Stories
if (!$orientation && ((get_site_variable('ROOSTER_ENABLED') == 2) || (get_site_variable('ROOSTER_DEV_ENABLED') == 2))) {
$rooster_story_count = get_site_variable('ROOSTER_STORY_COUNT');
if (!isset($rooster_story_count)) {
// Set default if something is wrong with the sitevar
$rooster_story_count = 2;
}
$rooster_stories = rooster_get_stories($user, $rooster_story_count, $log_omissions = true);
if (!empty($rooster_stories) && !empty($rooster_stories['stories'])) {
// Do page-view level logging here
foreach($rooster_stories['stories'] as $story) {
rooster_log_action($user, $story, ROOSTER_LOG_ACTION_VIEW);
}
tpl_set('rooster_stories', $rooster_stories);
}
}

// set the variables for the home announcement code
$hide_announcement_tpl = ($intro_settings | $HIDE_INTRO_BITMASK) & $HIDE_ANNOUNCEMENT_BIT;
// if on qa/dev site, special rules
$HIDE_INTRO_ON_DEV = get_site_variable('HIDE_INTRO_ON_DEV');
if ((IS_QA_SITE || IS_DEV_SITE) && !$HIDE_INTRO_ON_DEV) {
$hide_announcement_tpl = 0;
}

tpl_set('hide_announcement', $hide_announcement_tpl);
if ($is_candidate = is_candidate_user($user)) {
tpl_set('hide_announcement', false);
}
$home_announcement_tpl = !$hide_announcement_tpl || $is_candidate ? home_get_announcement_info($user) : 0;
tpl_set('home_announcement', $home_announcement_tpl);
tpl_set('hide_announcement_bit', $HIDE_ANNOUNCEMENT_BIT);

$show_friend_finder = !$orientation && contact_importer_enabled($user) && !user_get_hiding_pref($user, 'home_friend_finder');
tpl_set('show_friend_finder', $show_friend_finder);
if ($show_friend_finder && (user_get_friend_count($user) > 20)) {
tpl_set('friend_finder_hide_options', array('text' = > 'close', 'onclick' = > "return clearFriendFinder()"));
} else {
tpl_set('friend_finder_hide_options', null);
}

$account_info = user_get_account_info($user);
$account_create_time = $account_info['time'];

tpl_set('show_friend_finder_top', !$used_friend_finder);

tpl_set('user', $user);

// MONETIZATION BOX
$minimize_monetization_box = user_get_hiding_pref($user, 'home_monetization');
$show_monetization_box = (!$orientation && get_site_variable('HOMEPAGE_MONETIZATION_BOX'));
tpl_set('show_monetization_box', $show_monetization_box);
tpl_set('minimize_monetization_box', $minimize_monetization_box);

if ($show_monetization_box) {
$monetization_box_data = monetization_box_user_get_data($user);
txt_set('monetization_box_data', $monetization_box_data);
}

// ORIENTATION
if ($orientation) {
$network_ids = id_get_networks($user);
$network_names = multiget_network_name($network_ids);
$in_corp_network = in_array($GLOBALS['TYPE_CORP'], array_map('extract_network_type', $network_ids));
$show_corp_search = $in_corp_network || get_age(user_get_basic_info_attr($user, 'birthday')) >= 21;
$pending_hs = is_hs_pending_user($user);
$hs_id = null;
$hs_name = null;
if ($pending_hs) {
foreach(id_get_pending_networks($user) as $network) {
if (extract_network_type($network['network_key']) == $GLOBALS['TYPE_HS']) {
$hs_id = $network['network_key'];
$hs_name = network_get_name($hs_id);
break;
}
}
}
//$orientation_people = orientation_get_friend_and_inviter_ids($user);
$orientation_people = array('friends' = > user_get_all_friends($user), 'pending' = > array_keys(user_get_friend_requests($user)), 'inviters' = > array(), // wc: don't show inviters for now
);
$orientation_info = array_merge($orientation_people, array('network_names' = > $network_names, 'show_corp_search' = > $show_corp_search, 'pending_hs' = > array('hs_id' = > $hs_id, 'hs_name' = > $hs_name), 'user' = > $user, ));
tpl_set('orientation_info', $orientation_info);

tpl_set('simple_orientation_first_login', $get_o); // unused right now
}

// Roughly determine page length for ads
// first, try page length using right-hand panel
$ads_page_length_data = 3 + // 3 for profile pic + next step
($show_friend_finder ? 1 : 0) + ($show_status ? ($status_custom ? count($friends_status) : 0) : 0) + ($show_monetization_box ? 1 : 0) + ($show_birthdays ? count($birthdays) : 0) + count($new_pokes);

// page length using feed stories
if ($orientation) {
$ads_page_length_data = max($ads_page_length_data, count($stories) * 5);
}
tpl_set('ads_page_length_data', $ads_page_length_data);

$feed_stories = null;
if (!$orientation) { // if they're not in orientation they get other cool stuff
// ad_insert: the ad type to try to insert for the user
// (0 if we don't want to try an insert)
$ad_insert = get_site_variable('FEED_ADS_ENABLE_INSERTS');

$feed_off = false;

if (check_super($user) && $get_feeduser) {
$feed_stories = user_get_displayable_stories($get_feeduser, 0, null, $ad_insert);
} else if (can_see($user, $user, 'feed')) {
$feed_stories = user_get_displayable_stories($user, 0, null, $ad_insert);
} else {
$feed_off = true;
}

// Friend's Feed Selector - Requires dev.php constant
if (is_friendfeed_user($user)) {
$friendfeed = array();
$friendfeed['feeduser'] = $get_feeduser;
$friendfeed['feeduser_name'] = user_get_name($get_feeduser);
$friendfeed['friends'] = user_get_all_friends($user);
tpl_set('friendfeed', $friendfeed);
}

$feed_stories = feed_adjust_timezone($user, $feed_stories);

tpl_set('feed_off', $feed_off ? redirect('privacy.php?view=feeds', null, false) : false);
}
tpl_set('feed_stories', $feed_stories);

render_template($_SERVER['PHP_ROOT'].'/html/home.phpt');

search.php

< ?php /* * @author Mark Slee * * @package ubersearch */ ini_set('memory_limit', '100M'); // to be safe we are increasing the memory limit for search include_once $_SERVER['PHP_ROOT'].'/html/init.php'; // final lib include include_once $_SERVER['PHP_ROOT'].'/lib/s.php'; include_once $_SERVER['PHP_ROOT'].'/lib/browse.php'; include_once $_SERVER['PHP_ROOT'].'/lib/events.php'; include_once $_SERVER['PHP_ROOT'].'/lib/websearch_classifier/websearch_classifier.php'; flag_allow_guest(); $user = search_require_login(); if ($_POST) { $arr = us_flatten_checkboxes($_POST, array('ii')); $qs = '?'; foreach($arr as $key = > $val) {
$qs. = $key.'='.urlencode($val).'&';
}
$qs = substr($qs, 0, (strlen($qs) - 1));
redirect($_SERVER['PHP_SELF'].$qs);
}

// If they performed a classmates search, these values are
// needed to pre-populate dropdowns
param_get_slashed(array('hy' = > $PARAM_STRING, 'hs' = > $PARAM_INT, 'adv' = > $PARAM_EXISTS, 'events' = > $PARAM_EXISTS, 'groups' = > $PARAM_EXISTS, 'classmate' = > $PARAM_EXISTS, 'coworker' = > $PARAM_EXISTS));
$pos = strpos($get_hy, ':');
if ($pos !== false) {
$hsid = intval(substr($get_hy, 0, $pos));
$hsyear = intval(substr($get_hy, $pos + 1));
} else {
$hsid = intval($get_hs);
$hsyear = null;
}

tpl_set('hs_id', $hsid);
tpl_set('hs_name', get_high_school($hsid));
tpl_set('hs_year', $hsyear);
tpl_set('is_advanced_search', $get_adv);
tpl_set('user', $user);
tpl_set('count_total', 0); // pre-set count_total for the sake of ads page length

// Events search calendar data
param_get(array('k' = > $PARAM_HEX, 'n' = > $PARAM_SINT));

if (($get_k == search_module::get_key(SEARCH_MOD_EVENT, SEARCH_TYPE_AS))) {

$EVENTS_CAL_DAYS_AHEAD = 60;
$events_begin = strftime("%Y%m01"); // first of the month
$events_end = strftime("%Y%m%d", strtotime(strftime("%m/01/%Y")) + (86400 * $EVENTS_CAL_DAYS_AHEAD));
$events_params = array('dy1' = > $events_begin, 'dy2' = > $events_end);

param_get(array('c1' = > $PARAM_INT, 'c2' = > $PARAM_INT), 'evt_');
if (isset($evt_c1)) {
$events_params['c1'] = $evt_c1;
}
if (isset($evt_c2)) {
$events_params['c2'] = $evt_c2;
}
$results = events_get_calendar($user, $get_n, $events_params);
tpl_set('events_date', $results['events_date']);
}

// Holy shit, is this the cleanest fucking frontend file you've ever seen?!
ubersearch($_GET, $embedded = false, $template = true);

// Render it
render_template($_SERVER['PHP_ROOT'].'/html/s.phpt');

/**
* login function for s.php
*
* @author Philip Fung
*/

function search_require_login() {

//check if user is logged in
$user = require_login(true);

if($user 0 && !is_unregistered($user)) { return $user; }

// this is an unregistered user
param_get(
array('k' = > $GLOBALS['PARAM_HEX'], // search key (used by rest of ubersearch code)
));

global $get_k;
$search_key = $get_k;

//Let user see event or group search if criteria are obeyed
if ($search_key && (search_module::get_key_type($search_key) == SEARCH_MOD_EVENT || search_module::get_key_type($search_key) == SEARCH_MOD_GROUP) //event or group search
) {
return $user;
} else {
go_home();
}
}

为什么很多技术合伙人参与创业时会先谈钱?

编者按:本文来自缘创派创始人闫辉供稿,点此关注他的微博。

最近,收到一封缘创派用户的反馈:“我这二周谈了十几个技术合伙人。很多人并没有做好心理准备,只是希望找个兼职或者赚个外包。所以我用一个词形容他们叫叶公好龙。是否真的准备好创业,愿意承担风险和准备投入去做对于创业来讲非常重要。”这些朋友在抱怨:为什么找技术合伙人的时候,很多人会直白的谈到参与创业项目的费用呢?为什么很多只想先兼职呢?

这些创始人认为,既然我是在找合伙人,那大家就是要全情投入,立刻辞职,不拿薪水,共同奋斗,为了未来的收益而努力拼搏。你这上来朝我要钱,那怎么能算合伙人呢,这不就是外包和招聘了吗?

随着更多类似的抱怨,我开始仔细思考这个问题。有一次,我在我们的线下活动中对技术人员这个群体做了一些分析。告诉现场的一些创业主导者,为什么很多技术人员会这样做。大家听完之后,表示很认可。

因为我在 CSDN 工作过十多年,经常与技术人员打交道。比较了解他们的情况和思维模式。所以,我希望简单介绍一下,大家可以和技术合伙人互换一下角色,站在他们的角度来思考和观察创业。这样就能够更好地理解他们,并更好地合作。

技术人员与其他的创业者相比,有几个很大的不同:

一、技术人员的职业生涯很短暂,机会成本高,他们对风险的控制要求极高。

很久之前,就有“程序员和 ** 一样,都是吃青春饭”的说法。这并不是危言耸听,事实上,在中国,程序员的职业生涯的确有限制。从二十多岁到三十多岁,一般四十岁之后再编程就很难得到认可(现在,开始有很好的转变了。)而在这个期间,早期的几年还是处在学习的阶段,而在工作超过六年以后,很可能他在公司中会有强大的发展,获得了足够的重视。

其实,对于技术人员来说,只有中间寥寥几年会是技术水平可以,同时关注创业的时机。当他面临选择的时候,他考虑并不是所谓的虚拟的 1% 的成功机会带来的巨额回报,而是自己的职业发展向何处去。

技术人员评估风险主要有:技术成长和收入,其中技术成长的重要性更大。很多技术人员加入 BAT 这样的公司,除了收入不菲,更重要的因素就是这些公司的技术大牛多,自己的技术水平可以提高。而创业公司,往往是实现某个特定的业务,对他们的技术成长可能帮助不大。

我们都知道,95% 的创业项目会失败。如果失败,与主导创业者、市场或者运营人员相比,技术人员的损失和挫折感最大。因为,其他的创业者会感觉自己虽然没有成功,但得到了很多教训,这也是非常有价值的。但技术人员会认为,自己写的代码最终的价值等于零,这段时间的付出完全没有回报。如果技术再没有什么进步,这对他们的打击是致命性的。

这些原因造成他们对走出创业这一步的风险控制要求极高。再加上双方之前不认识,要基于陌生关系开始合作,这个信任基础需要逐步建立。

如果你还不相信,请看《乔布斯传》里的真实故事:沃茨负责 Apple 电脑的技术,当他把产品设计出来之后,乔布斯让沃茨出来创业成立公司一起做。沃茨直接拒绝了乔布斯,因为自己在惠普工作,他给乔布斯提议自己能不能先兼职干(要知道,他们两个是从小时候就认识的。请哪些感觉自己创业项目很 NB 的创始人体会一下。) 最后是乔布斯到沃茨家去哭,给他所有的亲戚打电话,逼着沃茨才出来的。这是因为,技术人员天生就是对风险控制的,他们是非常理性的人群,要他们去冒险需要更强的说服力。

所以,当对方提出来兼职的时候,不要把这个看作他们不想创业,不是技术合伙人。他们只是在控制风险,觉得没有到时机。

二、技术合伙人是互联网创业中前期最重要的实现者,但他们的核心价值是有阶段性和替代性的。

如果问你,在互联网创业中,技术合伙人重要吗?你肯定要说废话,当然重要。但很多创业项目的创始人并不是特别明白:技术合伙人什么时候最重要?

技术合伙人在开始阶段最重要。因为,只要是互联网创业项目,你总是需要要依托技术实现某个产品原型的。现在要想拿到投资,基本上很难凭一个 idea 了,至少需要一个原型,甚至是早期的产品上线。但事实上,因为找不到早期的技术人员参与,大部分人都折在只有一个创业项目的阶段。

所有的投资人都说,创业最重要的是团队,所以很多创始人想先找到合适的技术合伙人。这对于已经成型,有着良好磨合的创业团队,是毋庸置疑的。但对于很多项目来说,其实其实投资人主要看的团队是创始人自己,另外就是你的原型产品和早期的运营。所以,越早把你设想的产品做出来,运营起来,这才是最重要的。技术合伙人在这个阶段,最重要的任务是帮助你把产品做出来。

但是,双方之前不认识,没有磨合过,怎么办呢?这个信任基础从何而来的,钱其实是一种快速开始合作,进行磨合,并且建立初步信任的变通手段。

我分析过很多找到合伙人的案例,结论是:技术合伙人要钱并没有错,但不能按照外包的价格要钱。

我看到一个做手机游戏的创业项目,创始人给兼职的技术合伙人很少的一点钱,一个月 3000,技术人员便将自己所有的业余时间全部用来项目的开发,每天晚上都工作到 12 点,甚至到凌晨两点。这个参与者都表示:如果做出来产品,推到市场的有效果,那大家就可以全职出来做。这个创始人也表示,如果是雇佣或者外包,没有任何人会只拿 3 千块,用自己所有的业余时间辛苦做事的。

事实上,大部分创业项目,成功与否不在技术本身,而是在产品和运营。你只要找到一个愿意合作的技术合伙人,给一些象征性的费用,做出一个版本,上线运营测试一下,便能够知道自己的项目是否靠谱。在 36kr 的很多创业经验中,都提到过这种方式。

我个人感觉,如果对方要的费用如果在其薪资的 1/5 到 1/3 期间,不应该认为技术人员是为了钱,他们是为了控制风险。

三、技术人员的核心思维模式是质疑和要求短期回馈,这恰恰给了创始人主导项目的机会。

在创业团队中,创始人一定是最具有激情的哪个人。是他发现了一个市场空白,找到了一个机会,然后认为这就是成功的机会。于是说服了自己。

但是,技术人员恰恰相反,他们是极其理智的。因为长期和电脑打交道,形成的是逻辑性的思维。当外人给他讲述一个理念时,他的第一反应是质疑。是真的有这个需求吗?做出来有人用吗?怎么推广,怎么产生收入?很多时候,说服他们是非常困难的。

技术人员创业为什么很容易失败?因为他们只和计算机打交道,除了自己的需求,他们并不了解市场和用户。所以,他们自然对别人所讲的市场需求是质疑态度。

技术人员在编程的时候,逻辑就是有输入,就有输出,而且回馈速度越快越好,这个可能会影响技术人员的世界观的,他们希望得到回馈的周期短。

很多项目创始人表示,我愿意拿出超过 30% 甚至更多的股份给技术合伙人。其实,除了代表创始人不够成熟外,这样的许诺不仅技术人员不重视,甚至反而会招致技术人员更大的质疑:“是不是这个项目不靠谱,所以才让我先做呢?”

但是,这恰恰给创始人主导项目的机会。只要你能说服技术合伙人,稍微付出一些费用,这样就可以把项目的未来价值握在自己手中。一定要谨记,技术合伙人最重要的职责是理解业务,把产品做出来。在整个创业团队中,更倾向于一个实现者或者翻译的角色。不能指望技术合伙人对项目的理解和认同和自己一样。

相信很多人看到这里,还是会不屑的说:我觉得他们还不是合伙人。为什么不能不要钱,立刻和我光膀子干呢?

并不是没有这样的技术合伙人,也有很多创业团队组成之后,大家都不拿薪水。但我注意到,这种团队有几个特点:1. 大家都是技术或者产品背景,都参与具体的开发工作。所以大家不拿薪水感觉公平 2. 股份平均化。既然都不拿薪资,那大家的股份就会平均化。(但事实上,股份平均化对于创业项目来讲有很大的弊端。)

如果你想主导创业,如果自己不是技术背景的创业者,还是试着互换一下角色,去理解技术合伙人吧。毕竟,把项目做出来才是第一位的。而且,这个阶段其实是一个相互磨合,不断建立信任的过程。创始人要想把握项目的主动权,只凭借一个想法,而不是一些实际付出是不现实的。

最后再总结一下:

  1. 技术合伙人对创业想法首先是质疑的,他们要短期回报并不只看钱,是为了控制风险。
  2. 技术人员愿意参与你的项目,本身就在冒风险。因为一旦失败,他们失去的最多。
  3. 兼职是某些陌生合作下的过渡阶段,在合作中提升信任,最终成为真正的合伙人。

在微信看见的文章,很不错,就复制下来了,把心里话都说明白了,直接看这个了解技术员为啥和我们提创业,我们就要开口这个!

来源:http://www.36kr.com/p/206766.html?vt=0

Chrome模拟手机访问设置

新建标签页,按“F12”打开控制台,点右下角的小齿轮,在弹出的窗口选择Overrides选项卡,把User Agent勾上,在下面的下拉框选择你喜欢的手机UA,这样你就能把Chrome伪装成手机浏览器了。

      如果再把把右边的Override Geolocation也勾上,就可以模拟位置了,但需要我们自己设置位置坐标。步骤如下:
打开https://maps.google.com/ 找到你假冒的地点,右击鼠标,选择“这儿是什么?”? 然后搜索框就会显示当前的纬度和经度。(前一个是纬度,后一个是经度,我选了 18.292018 ,109.348437,是海南三亚的坐标)。根据刚才得到的经纬度设置成Lat = 18.292018, Lon = 109.348437。
记住,千万不要关闭控制台哦!
直接在上边的标签页登录手机QQ空间,切换到触屏版,然后在发布说说的时候试着添加位置坐标,看坐标是否假冒成功了。我经过测试发现,国内的位置基本上都能正确识别,但国外的坐标就不行了。比方我尝试了Google山寨城总部以及目田女神像的位置坐标,均未能识别。如果识别成功了,赶紧写点“旅游”后的感受吧,不然功夫就白费了。
经测试,腾讯微博也可以伪造发布地点,但新浪微博我尝试了几次均未能成功,有的网友说是发布成功了。最后看看我从三亚“天涯海角”发来的说说:

12款不容错过的新款jQuery插件

本文来自CodeGeekz,作者是Gavin。jQuery是一款快速、简明的JavaScript类库,jQuery的语法设计可以简化HTML文档对象、事件处理、选择DOM元素、制作动画效果、使用Ajax以及其他功能。其模块化的使用方式使开发者可以很轻松的开发出功能强大的静态或动态网页。

下面收集的这12款刚发布的jQuery插件将会对你的开发任务起到事半功倍的效果。

1. Responsive Elements

Responsive Elements作为jQuery的一个插件,使得在Web网页里需要使用元素这一过程变得更加简单。此插件在元素里添加各种类(如大于100、小于150小于200),这就能告诉我们“每个元素的确切大小是多少”。另外,使用这些预定义的类可以帮助我们为每一个场景创建不同的风格。类的范围(从X像素到Y像素)和类的区间也是可以自定义的。

2. CLNDR.js

CLNDR.js是一个jQuery插件,用于创建日历并且可以按自己需求随意定制。该插件没有产生任何标记,而是使用Underscore.js HTML模板填充数据。它还有“随时可用”选项确定星期抵消,日期会在最初加载的时候显示,随意点击事件(例如下一月/上一月)等功能。值得一提的是,CLNDR.js并不是一个利用玩的方式来创建日历的,而是一个功能丰富的、能把人们心目中想要的独一无二的日历创建出来的一个样板。

3. AnimateScroll

AnimateScroll只是一个很小的jQuery插件,其功能是为滚动添加相对宽松的效果。可以自定义滚动的风格(30个滚动效果)和滚动的速度。此外还有一个“填充”选项,用来控制滚动结束的位置。AnimateScroll插件并不仅仅局限于页面的整个部分,但特定包装器元素也可以有针对性。

4. JInvertScroll

JInvertScroll是一个能够巧妙地处理默认滚动行为同时可以实施水平滚动的jQuery插件。这个轻于1KB的轻量级插件无需安装就可以使用。添加一个特定的类来包装器元素和调用一个JavaScript函数就已经足够了。与此同时,它还简化了利用onScroll回调方式来创建视差效果的步骤,这个视差效果可以决定激活哪一个元素。

5. Intention.js

Dow Jones创建了Intention.js插件,它可以更加简便的开发出响应式布局。这个插件可以减少对CSS媒体查询的需求,还能为重组HTML提供一个高度灵活的解决方案。它有3个基本的操作方法、属性、类和配置,它们都可以用HTML属性来设置。Intention.js插件带有“随时可用”的设置,可以控制宽度临界值、触摸设备、高分辨率显示器和一个后退,所有的这些都是可以完全自定义的。

6. NProgress

NProgress插件是一个纳米进度条,应用于复杂网页的细长进度条。可以说它的来源是从Google、YouTube和Medium那里得到的创作灵感。以现实的细流动画为特色,来让你的用户相信有些重要的事情正在发生。插件NProgress.js对于Turbolinks、Pjax和其他的Ajax级别的App来说简直是完美的搭配。

7. Flowtype.js

FlowType.JS是一款jQuery插件,它能根据容器的宽度自动调整字体大小以及行间距,这样内容就能像我们想要的那样显示出来。

8. Failsafe.js

FailSafe.是一个可以在危险环境下帮助App正确运行的jQuery插件。换句话说,它甚至考虑到了在断网情况下和低电量情况下如何运行——插件会很友好的向用户发送提示信息。在某些断网或高电压情况下,这个插件无法正常使用网页上的一些元素。

9. jQuery Fullscreen Editor Plugin

这一插件可以将文本域转换到可定制的编辑器里,既可以在表格中使用也可以单独使用。如果在全屏编辑器里的时候可以调整最大宽度和高度,还可以在编辑器后面覆盖上一层半透明的覆盖物。切换全屏模式时候的过渡效果可以是淡入淡出式或滑入式的。

10. jQuery Tweetable.js 

Tweetable.js插件可以更加简便的把语句和代码片段tweet给你的用户。那样就抓住所有可tweet数据元素的属性,并创建可点击的链接。如果所说的属性有一个固定的值,那么tweet文本就会被设置成那个值。链接在默认的情况下是没有什么特色的,但是这些链接都是用给定的类创建的(默认情况下是可以tweet出去的)。

11. Glide.js

Glide.js是一款响应式和对触摸友好的jQuery滑块。基于CSS3转换实现,并在低版本浏览器降级处理。Glide.js简单,重量轻,快速,适用于智能手机,平板电脑和台式机。它支持Swipe事件,箭头和子弹导航,键盘导航,公共API回调,自动播放和悬停暂停功能。

12. EasyDropDown

EasyDropDown是一个jQuery插件,你可以毫不费力地将简陋的Select元素设置为可定制风格的下拉菜单,用于表单或者一般的导航。和著名的下拉插件Chosen很像,但是具有自己的特点,例如:简洁、语义标记、兼容表单验证、完整的键盘控制、滚动支持、在触摸设备上降级为原生UI等等众多优点。另外,提供了Default、Metro、Flat三套不同风格的主题,相信能够满足你的需要。