R package based on 'Rcpp' for 'MeCab': Yet Another Part-of-Speech and Morphological Analyzer. The purpose of this package is providing a seamless developing and analyzing environment for CJK texts. This package utilizes parallel programming for providing highly efficient text preprocessing 'posParallel()' function. For installation, please refer to README.md file.
| Version: | <IP_ADDRESS> |
| Depends: | R (≥ 3.4.0) |
| Imports: | Rcpp, RcppParallel |
| LinkingTo: | Rcpp, RcppParallel, BH |
| Published: | 2018-07-04 |
| Author: | Junhewk Kim [aut, cre], Taku Kudo [aut] |
| Maintainer: | Junhewk Kim <junhewk.kim at gmail.com> |
| BugReports: | https://github.com/junhewk/RcppMeCab/issues |
| License: | GPL-2 | GPL-3 [expanded from: GPL] |
| NeedsCompilation: | yes |
| SystemRequirements: | MeCab 0.996 (or mecab-ko 0.9.2) or higher, GNU make |
| Materials: | README NEWS |
| CRAN checks: | RcppMeCab results |
| Reference manual: | RcppMeCab.pdf |
| Package source: | RcppMeCab_<IP_ADDRESS>.tar.gz |
| Windows binaries: | r-devel: RcppMeCab_<IP_ADDRESS>.zip, r-release: RcppMeCab_<IP_ADDRESS>.zip, r-oldrel: RcppMeCab_<IP_ADDRESS>.zip |
| OS X binaries: | r-release: not available, r-oldrel: not available |
| Old sources: | RcppMeCab archive |
Please use the canonical form https://CRAN.R-project.org/package=RcppMeCab to link to this page.


Illustration by Florian Klimm. All code is freely available on Github. Raw data from the UK Parliament website.


I am presently employed as a research scientist at Ant Research. In my previous role, spanning from 2020 to 2023, I held the position of research associate professor within the School of Computer Science at Wuhan University. My academic journey includes the attainment of a Ph.D. degree from Wuhan University in 2020. Notably, from 2018 to 2020, the happiest period of my Ph.D. experience was spent as a visiting Ph.D. student under the mentorship of Prof. Tianfu Wu at NC State University. Prior to embarking on my Ph.D. pursuits, I earned my B.S. degree from the School of Mathematics and Statistics at Wuhan University in 2014.
My current research focus primarily revolves around the development of learning algorithms for the computation of structured visual geometry in the realm of computer vision, in particular to 3D vision problems. The profile photo accompanying my information is generated through the utilization of my HAWPv3. I greatly enjoy engaging in conversations with different people, so please don’t hesitate to initiate a chat if you share an interest in my work or would simply like to connect.
Recent News
| 2023. 07: | I will join Interatcion Intelligence Lab, Ant Research as a research scientist in this month. Farewell Wuhan University! |
| 2023. 06: | 毕业 and 毕业 👋! |
| 2023. 05: | I have been named one of the CVPR 2023 Outstanding Reviewers 🥰 |
| 2023. 03: | The code of Level-S2fM is online available. |
Selected Publications
Mentorship
- Wenchao Ma (2020-2023, M.S. )
- Gege Wei (2020-2023, M.S.)
- Xiangwei Jiang (2020-2023, M.S.)
- Can Wang (2021-2023, M.S.)
- Yuxi Xiao (2022-2023, Undergraduate student)


August 3, 2019
Few people will receive the maximum possible benefit, but how high is the maximum? The short answer is that the maximum monthly Social Security benefit that an individual who files a claim in {{CURRENT_YEAR}} can receive is:
${{maximumMonthlyBenefit | number}} / month
In order to reach this high of a benefit, someone must have:
You can see what the per-year maximum taxable earnings are from the Social Security Adminstration's maximum taxble income table.
At other filing ages, the maximum possible benefit would be smaller:
The social security calculator will allow you to see the benefit at any starting age, for any earnings record.
The spouse of someone earning the maximum monthly benefit would also be eligible to earn a spousal benefit on the same record of as much as half of the primary earner's benefit.
In the case of the primary earner earning the maximum benefit of ${{maximumMonthlyBenefit | number}} / month, the spouse would also be eligible for an additional maximum benefit of ${{spouseMax | number}} / month. This would take the total benefit for this family to ${{familyMax | number}} / month. If the spouse also had maxed out his or her own record, the total benefit for the two maximum personal benefits is simply double a single personal benefit, which is ${{maximumMonthlyBenefit * 2 | number}} / month.
Should someone who had high taxable income work more years to increase their social security benefit? The answer is usually no. Benefits grow more slowly as they approach the maximum. For example, imagine the same person earned fewer than 35 years at the maximum income:
Look at your personal benefit data find out how it will compare to these maximums.
Ask other 'What If?' questions. The tool is absolutely free.


Canvas
- FF, Chrome, Safari, IE 9+
- DiveIntoHtml5
- MDN
Drawing context
You need to get a "2D" drawing context.
NB: <canvas id="myCanvas" > is NOT self-closing.
var context = document.getElementById("myCanvas").getContext("2d");
You need to get a "2D" drawing context.
NB: <canvas id="myCanvas" > is NOT self-closing.
var context = document.getElementById("myCanvas").getContext("2d");


Author: Ken Krebs, Juergen Hoeller, Rob Harrop, Costin Leau, Sam Brannen, Scott Andrews
Level: Advanced
Technologies: JPA, Junit, JMX, Spring MVC Annotations, AOP, Spring Data, JSP, webjars, Dandellion
Summary: The spring-petclinic
quickstart shows how to run the Spring PetClinic Application in JBoss EAP using the JBoss EAP BOMs.
Target Product: JBoss EAP
Source: https://github.com/jboss-developer/jboss-eap-quickstarts/
The spring-petclinic
quickstart shows how to run the Spring PetClinic Application in Red Hat JBoss Enterprise Application Platform with the use of Red Hat JBoss EAP BOMs (for the best compatibility). One of the major changes is the use of the webapp/WEB-INF/jboss-deployment-structure.xml
file. This file specifies which modules to include or exclude when building the application. In this case, we exclude Hibernate libraries since the application uses Spring Data JPA. Additionally, this is only required when using the spring-data-jpa profile, see resources/spring/business-config.xml
.
For detailed explanation of the changes made to adapt the Quickstart to Red Hat JBoss Enterprise Application Platform see: CHANGES.md
PetClinic features alternative DAO implementations and application configurations for JDBC, JPA, and Spring Data JPA, with HSQLDB and MySQL as target databases. The default PetClinic configuration is JPA on HSQLDB.
src/main/resources/spring/business-config.xml
pulls in src/main/resources/spring/data-access.properties
to set the JDBC-related settings for the JPA EntityManager definition.
data-access.properties
switches between the data access strategies.webapp/WEB_INF/web.xml
the <param-name>spring.profiles.active</param-name>
using <param-value>jpa</param-value>
(as the default) refers to the bean to be used in src/main/resources/spring/business-config.xml
.
<param-value>
to jdbc
, jpa
, or spring-data-jpa
is all that is needed to change the DAO implementation.All versions of PetClinic also demonstrate JMX support via the use of <context:mbean-export/>
in resources/spring/tools-config.xml
for exporting MBeans. The CallMonitoringAspect.java
is exposed using Spring's @ManagedResource
and @ManagedOperation
annotations and with @Around
annotation we add monitoring around all org.springframework.stereotype.Repository *
functions. You can start up the JDK's JConsole to manage the exported bean.
The use of @Cacheable
is also demonstrated in ClinicServiceImpl.java
by caching the results of the method findVets
. The cacheManager in configured in tools-config.xml
and ehcache.xml
specifies the vets
cache properties.
The default transaction manager for JDBC is DataSourceTransactionManager and for JPA and Spring Data JPA, JpaTransactionManager. Those local strategies allow for working with any locally defined DataSource. These are defined in the business-config.xml
Note that the sample configurations for JDBC, JPA, and Spring Data JPA configure a DataSource from the Apachce Tomcat JDBC Pool project for connection pooling. See datasource-config.xml
.
The application this project produces is designed to be run on Red Hat JBoss Enterprise Application Platform 7.1 or later.
All you need to build this project is Java 8.0 (Java SDK 1.8) or later and Maven 3.3.1 or later. See Configure Maven for JBoss EAP 7.1 to make sure you are configured correctly for testing the quickstarts.
For Linux: EAP7_HOME/bin/standalone.sh
For Windows: EAP7_HOME\bin\standalone.bat
mvn clean package wildfly:deploy
This will deploy spring-petclinic/target/spring-petclinic.war
to the running instance of the server.
If you do not have maven configured you can manually copy spring-petclinic/target/spring-petclinic.war
to EAP7_HOME/standalone/deployments.
For MySQL, you need to use the corresponding schema and SQL scripts in the db/mysql
subdirectory.
In you intend to use a local DataSource, the JDBC settings can be adapted in src/main/resources/spring/datasource-config.xml
. To use a JTA DataSource, you need to set up corresponding DataSources in your Java EE container.
The application will be running at the following URL: http://localhost:8080/spring-petclinic/.
Note: You see the following warning in the server log when you access the application. This example does not provide a dandelion.properties
file because it does not require any changes to the dandelion default configuration. You can ignore this warning.
WARN [com.github.dandelion.core.config.StandardConfigurationLoader] (default task-1) No file "dandelion.properties" was found in "dandelion/dandelion.properties" (classpath). The default configuration will be used.
mvn wildfly:undeploy
This quickstart provides Arquillian functional tests as well. They are located in the functional-tests/
subdirectory under the root directory of this quickstart. Functional tests verify that your application behaves correctly from the user's point of view. The tests open a browser instance, simulate clicking around the page as a normal user would do, and then close the browser instance.
NOTE: The arquillian-based functional tests deploy the application, so be sure you have undeployed it before you begin. To run these tests, you must build the main project as described above.
mvn wildfly:undeploy
mvn clean package
Navigate to the functional-tests/ directory in this quickstart.
mvn clean verify -Parq-remote
If you prefer to run the functional tests using managed instance of the JBoss EAP server, meaning the tests will start the server for you, type the following command:
mvn clean verify -Parq-managed
The spring-petclinic
quickstart contains three configurations: JDBC, JPA, and Spring Data JPA. You should see the tests run 3 times, one for each configuration.
Review the server log. You will see an exception for each test configuration run similar to the following in the server log. This is intentional to demonstrate how exceptions are handled within application. This the same exception you can test by clicking on the Error
menu item in the upper right corner in the deployed application. The application shows a nice error page in the browser instead of the exception.
WARN [warn] (default task-15) Handler execution resulted in exception: java.lang.RuntimeException: Expected: controller used to showcase what happens when an exception is thrown
at org.springframework.samples.petclinic.web.CrashController.triggerException(CrashController.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
(remainder of StackTrace removed for readability)
You can also start the server and deploy the quickstarts or run the Arquillian tests from Eclipse using JBoss tools. For general information about how to import a quickstart, add a JBoss EAP server, and build and deploy a quickstart, see Use JBoss Developer Studio or Eclipse to Run the Quickstarts.
Note: Eclipse/JBDS may generate a persistence.xml file in the src/main/resources/META-INF/ directory. In order to avoid errors, delete this file.
If you want to debug the source code or look at the Javadocs of any library in the project, run either of the following commands to pull them into your local repository. The IDE should then detect them.
mvn dependency:sources
mvn dependency:resolve -Dclassifier=javadoc


|
Upcoming dropins in Gothenburg
|
Date
|
Time
|
University
|
Venue
|
|
Tue, Mar 3
|
10:00 - 11:00
|
GU
|
Medicinareg. 7b, corridor (map)
|
|
Mon, Mar 9
|
13:00 - 14:00
|
Chalmers
|
Physics building, fl.1, nano (map)
|
|
Tue, Mar 17
|
10:00 - 11:00
|
GU
|
Medicinareg. 7b, corridor (map)
|
|
Mon, Mar 23
|
13:00 - 14:00
|
Chalmers
|
Physics building, fl.1, nano (map)
|
|
Tue, Mar 31
|
10:00 - 11:00
|
GU
|
Medicinareg. 7b, corridor (map)
|
*Drop-ins at GU are now joint drop-ins together with staff from the Bioinformatics Core Facility.
Who is this for?
Anyone doing academic research having questions about bioinformatics!
Are you planning a new project? Are you stuck in some part of your
analysis? Do you need help interpreting the results? We are happy to
answer questions, small or large.
Who are we?
We are a local team of Bioinformatics scientists, part of the SciLifeLab
National Bioinformatics Infrastructure Sweden (NBIS). NBIS supports
Swedish life science research by providing bioinformatics support,
infrastructure and training, in the form of local dropins, free and paid
project support, PhD-student advisory program, national courses and
more. Visit https://nbis.se for further information.
|


| Monday 7 am - 8 am | Wednesday 7 am - 8 am | Friday 7 am - 8 am | |
| Monday 6 pm - 7:30 pm | Tuesday 6 pm - 7:30 pm | Wednesday 6 pm - 7:30 pm | Thursday 6 pm - 7:30 pm |
| Tuesday 4 pm - 5 pm | Thursday 4 pm - 5 pm | Saturday 10 am - 11 am | |
| Monday 5 pm - 6 pm | Tuesday 5 pm - 6 pm | Wednesday 5 pm - 6 pm | Thursday 5 pm - 6 pm |
| Wednesday 4 pm - 5 pm | Friday 5 pm - 6 pm |
| Saturday 8:30 am - 10 am |
| Saturday 11 am - 12 pm | |
| Saturday 6 pm - 7 pm | Sunday 6 pm - 7:30 pm |


{% extends "error.html" %} {% block content %}
The web page you seekcannot be located butendless others exist


Enables or disables a custom command or menu. Disabled commands appear dimmed and can't be chosen. Use ENABLE.COMMAND to control which commands the user can click in a menu bar.
Syntax
ENABLE.COMMAND(bar_num, menu, command, enable, subcommand)
Bar_num is the menu bar in which a command resides. Bar_num can be the number of a built-in menu bar or the number returned by a previously run ADD.BAR function. See ADD.COMMAND for a list of the built-in menu bar numbers.
Menu is the menu on which the command resides. Menu can be either the name of a menu as text or the number of a menu. Menus are numbered starting with 1 from the left of the screen.
Command is the command you want to enable or disable. Command can be either the name of the command as text or the number of the command. The top command on a menu is command 1. If command is 0, ENABLE.COMMAND enables or disables the entire menu.
Enable is a logical value specifying whether the command should be enabled or disabled. If enable is TRUE, Microsoft Excel enables the command; if FALSE, it disables the command.
Subcommand is the name of the command on a submenu that you want to enable. If you use subcommand, you must use command as the name of the submenu. Use subcommand 0 to enable an entire submenu.
Remarks
You cannot disable built-in commands. If the specified command is a built-in command or does not exist, ENABLE.COMMAND returns the #VALUE! error value and interrupts the macro.
You can hide any shortcut menu from users by using ENABLE.COMMAND with command set to 0.
Example
The following macro formula disables a custom command that had been added previously to the View menu on the worksheet and macro sheet menu bar:
ENABLE.COMMAND(10, "View", "Audit...", FALSE)
Related Functions
ADD.BAR Adds a menu bar
ADD.COMMAND Adds a command to a menu
CHECK.COMMAND Adds or deletes a check mark to or from a command
DELETE.COMMAND Deletes a command from a menu
RENAME.COMMAND Changes the name of a command or menu
Return to index


UE4 Integration 2.00
If you are experiencing an issue with the integration and none of the topics below help, visit to our Q&A Forum.
You should see a shortcut to the manual is available under the help menu, that means the plugin is in the right place and has been enabled.
If you see the FMOD Help in the manual, then the plugin installed correctly. If you don't see FMOD help, it isn't installed.
If you have modified the project output format in your FMOD Studio project, you will need to update your Unreal project settings to match.
This can be found under "Edit > Project Settings > FMOD Studio > Output Format". Keep in mind that this must match the Studio project settings in order for the mix to behave correctly.
The editor does not mark FMOD assets as read-only, so there is nothing stopping the user from trying to rearrange the folder structure.
However any such changes aren't going to change the underlying Studio project, so the changes will be lost next time Unreal is restarted.
The inbuilt Unreal asset serialization stores asset by full path, not by GUID. This means that if you rename events or folders in the Studio Tool, then any references in Unreal levels will be lost. For now the only workaround is to avoid renaming events or folders once you have started using them in levels.
See the Deployment page for information about issues with deployment.
If you Launch your game and there is no sound playing or there is error loading the FMODStudio module, it an issue with Deployment.
If Live Update is enabled and the FMOD Studio will error when it fails to open the required network port. If this is a problem, then Live Update can be disabled in the Project Settings window.
To help track down problems, verbose logging can be turned on for the FMOD UE4 integration. Add the following command line to the UE4 editor:
-LogCmds="LogFMOD verbose"


--- layout: page title: "Rework" prev: Rework_split_006.html next: Rework_split_008.html book_path: books/jason-fried-david-heinemeier-hansson-rework-_oeb/ --- {% include JB/setup %} {% raw %}
"That would never work in the real world." You hear it all the time when you tell people about a fresh idea.
This real world sounds like an awfully depressing place to live. It's a place where new ideas, unfamiliar approaches, and foreign concepts always lose. The only things that win are what people already know and do, even if those things are flawed and inefficient.
Scratch the surface and you'll find these "real world" inhabitants are filled with pessimism and despair. They expect fresh concepts to fail. They assume society isn't ready for or capable of change.
Even worse, they want to drag others down into their tomb. If you're hopeful and ambitious, they'll try to convince you your ideas are impossible. They'll say you're wasting your time.
Don't believe them. That world may be real for them, but it doesn't mean you have to live in it.
We know because our company fails the real-world test in all kinds of ways. In the real world, you can't have more than a dozen employees spread out in eight different cities on two continents. In the real world, you can't attract millions of customers without any salespeople or advertising. In the real world, you can't reveal your formula for success to the rest of the world. But we've done all those things and prospered.
The real world isn't a place, it's an excuse. It's a justification for not trying. It has nothing to do with you.


{% trans %}Create a new registration form{% endtrans %}
{% trans -%}
To create a new registration form, specify the title and participant visibility settings below.
The visibility settings can only be changed while there are no registrations.
{%- endtrans %}


Raymond "Red" Reddington, one of the FBI's most wanted fugitives, surrenders in person at FBI Headquarters in Washington, D.C.


Uber is still burning cash at an alarming rate
Uber expects to be profitable by 2021
by Shawn KnightIn context: Uber’s monthly active platform consumers (MAPCs), defined as the number of unique consumers who completed a ride or received an Eats meat at least once in a given month, climbed to 103 million for the quarter – up 26 percent from 82 million in the year-ago period.
Uber for the third quarter of 2019 reported revenue of $3.8 billion, an increase of 30 percent year-over-year, as gross bookings climbed 29 percent to $16.5 billion. Trips were also on the rise, from 1.3 billion in the year-ago period to 1.8 billion through the three-month period ending September 30 – an increase of 31 percent.
Despite the growth, however, Uber is still hemorrhaging money at an alarming rate. The company posted a net loss of $1.2 billion for the quarter, or roughly 18 percent more than it burned during the same period in 2018. That’s the third largest loss for Uber since the company started reported earnings in 2017 according to The Wall Street Journal.
Uber CEO Dara Khosrowshahi said in an interview after the earnings release that his company expects to reach adjusted EBITDA profitability in 2021.
Even still, Uber’s shareholders aren’t responding to the news favorably. As of writing, the stock is down 8.77 percent to $28.36 after closing at $31.08 yesterday afternoon.
Masthead credit: Uber app by Daniel Fung


Thanks to my family's unconditional support,I had the courage to study abroad. Sometimes my mom would text me and ask me what I was doing. I know she misses me. It's hard to be so far away from my family. But I know I am not alone.
Entertainment
I am a big fan of K-pop. I love everything about korean tv shows, food and stars! My friends often joke that I am a Korean. I plan to learn some korean in this summer. Hopefully oneday I can go to Korea to see my idols!
Community
There are about 15 students who study abroad like me in our apartment. We have known each other since we were in China. We oftern go to travel together. In some Chinese traditional holidaies, we would throw a party in someone's home.
School
I spent the first two year of college in Sichuan University-Pittsburgh Institue. It was the first time that I left my home and start a new life in a place I have never been.


Enjin is a small and (hopefully) easy to learn 2D game engine for the HTML5 canvas element.
It has all the features you'd expect from an engine, and can easily be extended by writing a new module and adding it alongside the rest of the requires in src/core.js
Check out example code in the Example folder, and see them in action at the showcase.
To build, just clone this repo, npm install
, and then npm run build
. You should have an "enjin.js" file in the public folder.
For developing, install the dev dependencies and run grunt serve
. Your browser should open a page at localhost:8100 which will automatically rebuild and reload when you edit any file in the src/ directory.


Kieran Milligan
Full Stack Web and Hybrid Mobile Applications Developer
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
- It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
- It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
Core Competencies
- Contrary to popular belief,
- Lorem Ipsum is not simply random text.
- It has roots in a piece of classical Latin literature from 45 BC
- making it over 2000 years old.
Certifications / Technical Proficiencies
| Certifications: | Certified Scrum Master |
| Platforms: | Linux, Windows, LAMP, JAM, NodeJS |
| Databases/CMS: | MySQL, PHP, Firebase, AWS, WordPress, Netlify |
| Tools: | VSCode, Atom, SSH, Git, GraphQL, NPM, React, Gatsby, Angular |
| Languages: | HTML, CSS, JavaScript, ES6, JSX, PHP, Bash, SQL |
Professional Experience
Company 1
Dates
Brief Company Description
Job Title- Contrary to popular belief, Lorem Ipsum is not simply random text.
- Contrary to popular belief, Lorem Ipsum is not simply random text.
- Contrary to popular belief, Lorem Ipsum is not simply random text.
- Contrary to popular belief, Lorem Ipsum is not simply random text.
Education
School Name - City Dates Attended
Degree / CertificationSchool Name - City Dates Attended
Degree / Certification


On the Manage sellers page, you can decide who is allowed to publish services to a marketplace. Depending on whether the marketplace you select is an open marketplace or a marketplace for authorized sellers only, different options are available:
- Marketplace for authorized sellers: If the marketplace allows only authorized sellers, you have to admit one or more supplier, broker, or reseller organizations that are to be allowed to publish services to it. When the marketplace is created, the organization specified as the marketplace owner is automatically admitted, provided that it is assigned the supplier, broker, or reseller role.
As the marketplace owner, you can revoke the publishing approval for a seller at any time, for example if he is in arrears with his payments. If the seller already published services to the marketplace, these services are automatically deactivated. Customers can no longer subscribe to them. Existing subscriptions are not affected.
- Open marketplace: If the marketplace allows any supplier, broker, or reseller to publish services, you can explicitly exclude one or more sellers and add them to a blacklist. This might be required, for example, if a seller is in arrears with his payments. If the seller already published services to the marketplace, these services are automatically deactivated. Customers can no longer subscribe to them. Existing subscriptions are not affected.
You can allow a seller who has been excluded from the marketplace to publish services again at any time, for example if he is not in arrears with his payments any longer.
To manage the sellers for a marketplace:
-
From the Marketplace list, select the marketplace for which you want to manage sellers.
The list contains all marketplaces to which you have access as a marketplace manager.
The Sellers field shows whether the marketplace is open to any seller or whether it is for authorized sellers only.
-
Depending on the seller policy defined for the selected marketplace, proceed as follows:
- Marketplace for authorized sellers: Allow sellers to publish services or exclude sellers from publishing services. Click here for more details.
- Open marketplace: Exclude sellers from publishing services or allow excluded sellers to publish services again. Click here for more details.


Enable SIP with Munki
15 Dec 2016When 10.12.2 hit this week, it introduced an awesome new feature - the ability to enable SIP without having to be booted into a Recovery like environment (either Recovery HD or a NetInstall). Unfortunately it merely enables SIP on the next reboot.
Fortunately, Munki is pretty good at telling users when they need to reboot, so I wrote the following pkgsinfo file that will check if SIP is enabled, and if it isn’t, will enable it and reboot (fortunately it’s quite a bit easier to do this that it is with other tools. I’ve targeted this update at 10.12.0, because, well, if they’re not updating, I’d like them to. And it’s called ‘Critical Security Update’ so they may actually install it. If you really want them to install it, you can set a force_install_after_date
and set it to the past, which will give your users a hour to install it before their machine goes byebye. Without further ado, here it is:
If you have machines that are below 10.12 (and considering the security issues, you should consider making 10.12 a managed install), you will probably want to add it to a manifest like so:


--- layout: post title: Original form design date: 2010-03-29 23:37:48.000000000 +02:00 type: post published: true status: publish categories: - Web development tags: - creativity - design - forms meta: _edit_last: '1' bfa_ata_body_title: Original form design bfa_ata_display_body_title: '' bfa_ata_body_title_multi: Original form design bfa_ata_meta_title: '' bfa_ata_meta_keywords: '' bfa_ata_meta_description: '' _sexybookmarks_shortUrl: http://b2l.me/atxqjt _sexybookmarks_permaHash: 8676eab7b03cb3beb5eccebdf2637d01 dsq_thread_id: '200179624' author: login: bbWebdesign email<EMAIL_ADDRESS>display_name: Bob first_name: Bob last_name: Belderbos ---
I just stumbled upon this article: "Mad Libs" Style Form Increases Conversion 25-40%
Quite amazing how a redesign can lead to a greater response. It makes sense though, a lot of forms on the web are boring. Making it a story or apply some creative styling makes it much less cumbersome to submit information.
It stresses once more you should design with the end-user in mind. What for you seems a one-minute form could be a real pain for the end user. Making it attractive, fun or offer something in return will increase returning visitors.


Services: {{ finding["ServicesCount"] }}
Infrastructure Modification Actions: {{ finding["ActionsCount"] }}
Type: {% if finding["Type"] == "Policy" %}Managed{% else %}Inline{% endif %} Policy
{% if finding["AssumableByComputeService"]|length > 0 %}
Role Assumable by Service(s): {% for service in finding["AssumableByComputeService"] %}{{ service }}{% if not loop.last %}, {% endif %}{% endfor %}
{% endif %}


[Node.js](http://nodejs.org) is a platform based on Chrome's JavaScript runtime,
called [V8](http://code.google.com/p/v8/). It allows you to develop all kinds of
software using JavaScript.
A great feature of Node.js is its wide variety of existing libraries and tools.
As the developer community is absolutely massive and incredibly active, Node.js
has a basic package manager called NPM that you can use to install Node.js-based
software and libraries from the command line.
While `MVC-NG-Boilderplate` makes heavy use of Node.js behind the scenes, you as the
application developer don't need to really think about it much. Most of the
interaction with Node.js will occur through Grunt, so you
really only need to know how get the initial setup working.
[Git](http://git-scm.com/) is a distributed version control system.
`MVC-NG-Boilerplate` uses git to manage its codebase. While in theory you don't have
to use Git once you download `MVC-NG-Boilerplate`, this project makes the assumption
that you do. If you're on GitHub, I assume you already have a basic
understanding of Git, which is all you need to make effective use of this
project.
If you're not familiar with it, check out the documentation linked to above.
GitHub also has a great [help section](https://help.github.com/). Bower package manager makes use of this to install packages.


C0 code coverage information
Generated on Sat Jun 07 16:45:06 +1000 2008 with rcov <IP_ADDRESS>
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 # rcov Copyright (c) 2004-2006 Mauricio Fernandez<EMAIL_ADDRESS>2 #
3 # See LEGAL and LICENSE for licensing information.
4
5 # NOTE: if you're reading this in the XHTML code coverage report generated by
6 # rcov, you'll notice that only code inside methods is reported as covered,
7 # very much like what happens when you run it with --test-unit-only.
8 # This is due to the fact that we're running rcov on itself: the code below is
9 # already loaded before coverage tracing is activated, so only code inside
10 # methods is actually executed under rcov's inspection.
11
12 require 'rcov/version'
13
14 SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
15
16 module Rcov
17
18 # Rcov::CoverageInfo is but a wrapper for an array, with some additional
19 # checks. It is returned by FileStatistics#coverage.
20 class CoverageInfo
21 def initialize(coverage_array)
22 @cover = coverage_array.clone
23 end
24
25 # Return the coverage status for the requested line. There are four possible
26 # return values:
27 # * nil if there's no information for the requested line (i.e. it doesn't exist)
28 # * true if the line was reported by Ruby as executed
29 # * :inferred if rcov inferred it was executed, despite not being reported
30 # by Ruby.
31 # * false otherwise, i.e. if it was not reported by Ruby and rcov's
32 # heuristics indicated that it was not executed
33 def [](line)
34 @cover[line]
35 end
36
37 def []=(line, val) # :nodoc:
38 unless [true, false, :inferred].include? val
39 raise RuntimeError, "What does #{val} mean?"
40 end
41 return if line < 0 || line >= @cover.size
42 @cover[line] = val
43 end
44
45 # Return an Array holding the code coverage information.
46 def to_a
47 @cover.clone
48 end
49
50 def method_missing(meth, *a, &b) # :nodoc:
51 @cover.send(meth, *a, &b)
52 end
53 end
54
55 # A FileStatistics object associates a filename to:
56 # 1. its source code
57 # 2. the per-line coverage information after correction using rcov's heuristics
58 # 3. the per-line execution counts
59 #
60 # A FileStatistics object can be therefore be built given the filename, the
61 # associated source code, and an array holding execution counts (i.e. how many
62 # times each line has been executed).
63 #
64 # FileStatistics is relatively intelligent: it handles normal comments,
65 # <tt>=begin/=end</tt>, heredocs, many multiline-expressions... It uses a
66 # number of heuristics to determine what is code and what is a comment, and to
67 # refine the initial (incomplete) coverage information.
68 #
69 # Basic usage is as follows:
70 # sf = FileStatistics.new("foo.rb", ["puts 1", "if true &&", " false",
71 # "puts 2", "end"], [1, 1, 0, 0, 0])
72 # sf.num_lines # => 5
73 # sf.num_code_lines # => 5
74 # sf.coverage[2] # => true
75 # sf.coverage[3] # => :inferred
76 # sf.code_coverage # => 0.6
77 #
78 # The array of strings representing the source code and the array of execution
79 # counts would normally be obtained from a Rcov::CodeCoverageAnalyzer.
80 class FileStatistics
81 attr_reader :name, :lines, :coverage, :counts
82 def initialize(name, lines, counts, comments_run_by_default = false)
83 @name = name
84 @lines = lines
85 initial_coverage = counts.map{|x| (x || 0) > 0 ? true : false }
86 @coverage = CoverageInfo.new initial_coverage
87 @counts = counts
88 @is_begin_comment = nil
89 # points to the line defining the heredoc identifier
90 # but only if it was marked (we don't care otherwise)
91 @heredoc_start = Array.new(lines.size, false)
92 @multiline_string_start = Array.new(lines.size, false)
93 extend_heredocs
94 find_multiline_strings
95 precompute_coverage comments_run_by_default
96 end
97
98 # Merge code coverage and execution count information.
99 # As for code coverage, a line will be considered
100 # * covered for sure (true) if it is covered in either +self+ or in the
101 # +coverage+ array
102 # * considered <tt>:inferred</tt> if the neither +self+ nor the +coverage+ array
103 # indicate that it was definitely executed, but it was <tt>inferred</tt>
104 # in either one
105 # * not covered (<tt>false</tt>) if it was uncovered in both
106 #
107 # Execution counts are just summated on a per-line basis.
108 def merge(lines, coverage, counts)
109 coverage.each_with_index do |v, idx|
110 case @coverage[idx]
111 when :inferred
112 @coverage[idx] = v || @coverage[idx]
113 when false
114 @coverage[idx] ||= v
115 end
116 end
117 counts.each_with_index{|v, idx| @counts[idx] += v }
118 precompute_coverage false
119 end
120
121 # Total coverage rate if comments are also considered "executable", given as
122 # a fraction, i.e. from 0 to 1.0.
123 # A comment is attached to the code following it (RDoc-style): it will be
124 # considered executed if the the next statement was executed.
125 def total_coverage
126 return 0 if @coverage.size == 0
127 @coverage.inject(0.0) {|s,a| s + (a ? 1:0) } / @coverage.size
128 end
129
130 # Code coverage rate: fraction of lines of code executed, relative to the
131 # total amount of lines of code (loc). Returns a float from 0 to 1.0.
132 def code_coverage
133 indices = (0...@lines.size).select{|i| is_code? i }
134 return 0 if indices.size == 0
135 count = 0
136 indices.each {|i| count += 1 if @coverage[i] }
137 1.0 * count / indices.size
138 end
139
140 # Number of lines of code (loc).
141 def num_code_lines
142 (0...@lines.size).select{|i| is_code? i}.size
143 end
144
145 # Total number of lines.
146 def num_lines
147 @lines.size
148 end
149
150 # Returns true if the given line number corresponds to code, as opposed to a
151 # comment (either # or =begin/=end blocks).
152 def is_code?(lineno)
153 unless @is_begin_comment
154 @is_begin_comment =<EMAIL_ADDRESS>false)
155 pending = []
156 state = :code
157 @lines.each_with_index do |line, index|
158 case state
159 when :code
160 if /^=begin\b/ =~ line
161 state = :comment
162 pending << index
163 end
164 when :comment
165 pending << index
166 if /^=end\b/ =~ line
167 state = :code
168 pending.each{|idx| @is_begin_comment[idx] = true}
169 pending.clear
170 end
171 end
172 end
173 end
174 @lines[lineno] && !@is_begin_comment[lineno] &&
175 @lines[lineno] !~ /^\s*(#|$)/
176 end
177
178 private
179
180 def find_multiline_strings
181 state = :awaiting_string
182 wanted_delimiter = nil
183 string_begin_line = 0
184 @lines.each_with_index do |line, i|
185 matching_delimiters = Hash.new{|h,k| k}
186 matching_delimiters.update("{" => "}", "[" => "]", "(" => ")")
187 case state
188 when :awaiting_string
189 # very conservative, doesn't consider the last delimited string but
190 # only the very first one
191 if md = /^[^#]*%(?:[qQ])?(.)/.match(line)
192 wanted_delimiter = /(?!\\).#{Regexp.escape(matching_delimiters[md[1]])}/
193 # check if closed on the very same line
194 # conservative again, we might have several quoted strings with the
195 # same delimiter on the same line, leaving the last one open
196 unless wanted_delimiter.match(md.post_match)
197 state = :want_end_delimiter
198 string_begin_line = i
199 end
200 end
201 when :want_end_delimiter
202 @multiline_string_start[i] = string_begin_line
203 if wanted_delimiter.match(line)
204 state = :awaiting_string
205 end
206 end
207 end
208 end
209
210 def precompute_coverage(comments_run_by_default = true)
211 changed = false
212 lastidx = lines.size - 1
213 if (!is_code?(lastidx) || /^__END__$/ =~ @lines[-1]) && !@coverage[lastidx]
214 # mark the last block of comments
215 @coverage[lastidx] ||= :inferred
216 (lastidx-1).downto(0) do |i|
217 break if is_code?(i)
218 @coverage[i] ||= :inferred
219 end
220 end
221 (0...lines.size).each do |i|
222 next if @coverage[i]
223 line = @lines[i]
224 if /^\s*(begin|ensure|else|case)\s*(?:#.*)?$/ =~ line && next_expr_marked?(i) or
225 /^\s*(?:end|\})\s*(?:#.*)?$/ =~ line && prev_expr_marked?(i) or
226 /^\s*(?:end\b|\})/ =~ line && prev_expr_marked?(i) && next_expr_marked?(i) or
227 /^\s*rescue\b/ =~ line && next_expr_marked?(i) or
228 /(do|\{)\s*(\|[^|]*\|\s*)?(?:#.*)?$/ =~ line && next_expr_marked?(i) or
229 prev_expr_continued?(i) && prev_expr_marked?(i) or
230 comments_run_by_default && !is_code?(i) or
231 /^\s*((\)|\]|\})\s*)+(?:#.*)?$/ =~ line && prev_expr_marked?(i) or
232 prev_expr_continued?(i+1) && next_expr_marked?(i)
233 @coverage[i] ||= :inferred
234 changed = true
235 end
236 end
237 (@lines.size-1).downto(0) do |i|
238 next if @coverage[i]
239 if !is_code?(i) and @coverage[i+1]
240 @coverage[i] = :inferred
241 changed = true
242 end
243 end
244
245 extend_heredocs if changed
246
247 # if there was any change, we have to recompute; we'll eventually
248 # reach a fixed point and stop there
249 precompute_coverage(comments_run_by_default) if changed
250 end
251
252 require 'strscan'
253 def extend_heredocs
254 i = 0
255 while i < @lines.size
256 unless is_code? i
257 i += 1
258 next
259 end
260 #FIXME: using a restrictive regexp so that only <<[A-Z_a-z]\w*
261 # matches when unquoted, so as to avoid problems with 1<<2
262 # (keep in mind that whereas puts <<2 is valid, puts 1<<2 is a
263 # parse error, but a = 1<<2 is of course fine)
264 scanner = StringScanner.new(@lines[i])
265 j = k = i
266 loop do
267 scanned_text = scanner.search_full(/<<(-?)(?:(['"`])((?:(?!\2).)+)\2|([A-Z_a-z]\w*))/,
268 true, true)
269 # k is the first line after the end delimiter for the last heredoc
270 # scanned so far
271 unless scanner.matched?
272 i = k
273 break
274 end
275 term = scanner[3] || scanner[4]
276 # try to ignore symbolic bitshifts like 1<<LSHIFT
277 ident_text = "<<#{scanner[1]}#{scanner[2]}#{term}#{scanner[2]}"
278 if scanned_text[/\d+\s*#{Regexp.escape(ident_text)}/]
279 # it was preceded by a number, ignore
280 i = k
281 break
282 end
283 must_mark = []
284 end_of_heredoc = (scanner[1] == "-") ?
285 /^\s*#{Regexp.escape(term)}$/ : /^#{Regexp.escape(term)}$/
286 loop do
287 break if j == @lines.size
288 must_mark << j
289 if end_of_heredoc =~ @lines[j]
290 must_mark.each do |n|
291 @heredoc_start[n] = i
292 end
293 if (must_mark + [i]).any?{|lineidx| @coverage[lineidx]}
294 @coverage[i] ||= :inferred
295 must_mark.each{|lineidx| @coverage[lineidx] ||= :inferred}
296 end
297 # move the "first line after heredocs" index
298 k = (j += 1)
299 break
300 end
301 j += 1
302 end
303 end
304
305 i += 1
306 end
307 end
308
309 def next_expr_marked?(lineno)
310 return false if lineno >= @lines.size
311 found = false
312 idx =<EMAIL_ADDRESS>do |i|
313 next unless is_code? i
314 found = true
315 break i
316 end
317 return false unless found
318 @coverage[idx]
319 end
320
321 def prev_expr_marked?(lineno)
322 return false if lineno <= 0
323 found = false
324 idx = (lineno-1).downto(0) do |i|
325 next unless is_code? i
326 found = true
327 break i
328 end
329 return false unless found
330 @coverage[idx]
331 end
332
333 def prev_expr_continued?(lineno)
334 return false if lineno <= 0
335 return false if lineno >= @lines.size
336 found = false
337 if @multiline_string_start[lineno] &&
338 @multiline_string_start[lineno] < lineno
339 return true
340 end
341 # find index of previous code line
342 idx = (lineno-1).downto(0) do |i|
343 if @heredoc_start[i]
344 found = true
345 break @heredoc_start[i]
346 end
347 next unless is_code? i
348 found = true
349 break i
350 end
351 return false unless found
352 #TODO: write a comprehensive list
353 if is_code?(lineno) && /^\s*((\)|\]|\})\s*)+(?:#.*)?$/.match(@lines[lineno])
354 return true
355 end
356 #FIXME: / matches regexps too
357 # the following regexp tries to reject #{interpolation}
358 r = /(,|\.|\+|-|\*|\/|<|>|%|&&|\|\||<<|\(|\[|\{|=|and|or|\\)\s*(?:#(?![{$@]).*)?$/.match @lines[idx]
359 # try to see if a multi-line expression with opening, closing delimiters
360 # started on that line
361 [%w!( )!].each do |opening_str, closing_str|
362 # conservative: only consider nesting levels opened in that line, not
363 # previous ones too.
364 # next regexp considers interpolation too
365 line = @lines[idx].gsub(/#(?![{$@]).*$/, "")
366 opened = line.scan(/#{Regexp.escape(opening_str)}/).size
367 closed = line.scan(/#{Regexp.escape(closing_str)}/).size
368 return true if opened - closed > 0
369 end
370 if /(do|\{)\s*\|[^|]*\|\s*(?:#.*)?$/.match @lines[idx]
371 return false
372 end
373
374 r
375 end
376 end
377
378
379 autoload :RCOV__, "rcov/lowlevel.rb"
380
381 class DifferentialAnalyzer
382 require 'thread'
383 @@mutex = Mutex.new
384
385 def initialize(install_hook_meth, remove_hook_meth, reset_meth)
386 @cache_state = :wait
387 @start_raw_data = data_default
388 @end_raw_data = data_default
389 @aggregated_data = data_default
390 @install_hook_meth = install_hook_meth
391 @remove_hook_meth= remove_hook_meth
392 @reset_meth= reset_meth
393 end
394
395 # Execute the code in the given block, monitoring it in order to gather
396 # information about which code was executed.
397 def run_hooked
398 install_hook
399 yield
400 ensure
401 remove_hook
402 end
403
404 # Start monitoring execution to gather information. Such data will be
405 # collected until #remove_hook is called.
406 #
407 # Use #run_hooked instead if possible.
408 def install_hook
409 @start_raw_data = raw_data_absolute
410 Rcov::RCOV__.send(@install_hook_meth)
411 @cache_state = :hooked
412 @@mutex.synchronize{ self.class.hook_level += 1 }
413 end
414
415 # Stop collecting information.
416 # #remove_hook will also stop collecting info if it is run inside a
417 # #run_hooked block.
418 def remove_hook
419 @@mutex.synchronize do
420 self.class.hook_level -= 1
421 Rcov::RCOV__.send(@remove_hook_meth) if self.class.hook_level == 0
422 end
423 @end_raw_data = raw_data_absolute
424 @cache_state = :done
425 # force computation of the stats for the traced code in this run;
426 # we cannot simply let it be if self.class.hook_level == 0 because
427 # some other analyzer could install a hook, causing the raw_data_absolute
428 # to change again.
429 # TODO: lazy computation of raw_data_relative, only when the hook gets
430 # activated again.
431 raw_data_relative
432 end
433
434 # Remove the data collected so far. Further collection will start from
435 # scratch.
436 def reset
437 @@mutex.synchronize do
438 if self.class.hook_level == 0
439 # Unfortunately there's no way to report this as covered with rcov:
440 # if we run the tests under rcov self.class.hook_level will be >= 1 !
441 # It is however executed when we run the tests normally.
442 Rcov::RCOV__.send(@reset_meth)
443 @start_raw_data = data_default
444 @end_raw_data = data_default
445 else
446 @start_raw_data = @end_raw_data = raw_data_absolute
447 end
448 @raw_data_relative = data_default
449 @aggregated_data = data_default
450 end
451 end
452
453 protected
454
455 def data_default
456 raise "must be implemented by the subclass"
457 end
458
459 def self.hook_level
460 raise "must be implemented by the subclass"
461 end
462
463 def raw_data_absolute
464 raise "must be implemented by the subclass"
465 end
466
467 def aggregate_data(aggregated_data, delta)
468 raise "must be implemented by the subclass"
469 end
470
471 def compute_raw_data_difference(first, last)
472 raise "must be implemented by the subclass"
473 end
474
475 private
476 def raw_data_relative
477 case @cache_state
478 when :wait
479 return @aggregated_data
480 when :hooked
481 new_start = raw_data_absolute
482 new_diff = compute_raw_data_difference(@start_raw_data, new_start)
483 @start_raw_data = new_start
484 when :done
485 @cache_state = :wait
486 new_diff = compute_raw_data_difference(@start_raw_data,
487 @end_raw_data)
488 end
489
490 aggregate_data(@aggregated_data, new_diff)
491
492 @aggregated_data
493 end
494
495 end
496
497 # A CodeCoverageAnalyzer is responsible for tracing code execution and
498 # returning code coverage and execution count information.
499 #
500 # Note that you must <tt>require 'rcov'</tt> before the code you want to
501 # analyze is parsed (i.e. before it gets loaded or required). You can do that
502 # by either invoking ruby with the <tt>-rrcov</tt> command-line option or
503 # just:
504 # require 'rcov'
505 # require 'mycode'
506 # # ....
507 #
508 # == Example
509 #
510 # analyzer = Rcov::CodeCoverageAnalyzer.new
511 # analyzer.run_hooked do
512 # do_foo
513 # # all the code executed as a result of this method call is traced
514 # end
515 # # ....
516 #
517 # analyzer.run_hooked do
518 # do_bar
519 # # the code coverage information generated in this run is aggregated
520 # # to the previously recorded one
521 # end
522 #
523 # analyzer.analyzed_files # => ["foo.rb", "bar.rb", ... ]
524 # lines, marked_info, count_info = analyzer.data("foo.rb")
525 #
526 # In this example, two pieces of code are monitored, and the data generated in
527 # both runs are aggregated. +lines+ is an array of strings representing the
528 # source code of <tt>foo.rb</tt>. +marked_info+ is an array holding false,
529 # true values indicating whether the corresponding lines of code were reported
530 # as executed by Ruby. +count_info+ is an array of integers representing how
531 # many times each line of code has been executed (more precisely, how many
532 # events where reported by Ruby --- a single line might correspond to several
533 # events, e.g. many method calls).
534 #
535 # You can have several CodeCoverageAnalyzer objects at a time, and it is
536 # possible to nest the #run_hooked / #install_hook/#remove_hook blocks: each
537 # analyzer will manage its data separately. Note however that no special
538 # provision is taken to ignore code executed "inside" the CodeCoverageAnalyzer
539 # class. At any rate this will not pose a problem since it's easy to ignore it
540 # manually: just don't do
541 # lines, coverage, counts = analyzer.data("/path/to/lib/rcov.rb")
542 # if you're not interested in that information.
543 class CodeCoverageAnalyzer < DifferentialAnalyzer
544 @hook_level = 0
545 # defined this way instead of attr_accessor so that it's covered
546 def self.hook_level # :nodoc:
547 @hook_level
548 end
549 def self.hook_level=(x) # :nodoc:
550 @hook_level = x
551 end
552
553 def initialize
554 @script_lines__ = SCRIPT_LINES__
555 super(:install_coverage_hook, :remove_coverage_hook,
556 :reset_coverage)
557 end
558
559 # Return an array with the names of the files whose code was executed inside
560 # the block given to #run_hooked or between #install_hook and #remove_hook.
561 def analyzed_files
562 update_script_lines__
563 raw_data_relative.select do |file, lines|
564 @script_lines__.has_key?(file)
565 end.map{|fname,| fname}
566 end
567
568 # Return the available data about the requested file, or nil if none of its
569 # code was executed or it cannot be found.
570 # The return value is an array with three elements:
571 # lines, marked_info, count_info = analyzer.data("foo.rb")
572 # +lines+ is an array of strings representing the
573 # source code of <tt>foo.rb</tt>. +marked_info+ is an array holding false,
574 # true values indicating whether the corresponding lines of code were reported
575 # as executed by Ruby. +count_info+ is an array of integers representing how
576 # many times each line of code has been executed (more precisely, how many
577 # events where reported by Ruby --- a single line might correspond to several
578 # events, e.g. many method calls).
579 #
580 # The returned data corresponds to the aggregation of all the statistics
581 # collected in each #run_hooked or #install_hook/#remove_hook runs. You can
582 # reset the data at any time with #reset to start from scratch.
583 def data(filename)
584 raw_data = raw_data_relative
585 update_script_lines__
586 unless @script_lines__.has_key?(filename) &&
587 raw_data.has_key?(filename)
588 return nil
589 end
590 refine_coverage_info(@script_lines__[filename], raw_data[filename])
591 end
592
593 # Data for the first file matching the given regexp.
594 # See #data.
595 def data_matching(filename_re)
596 raw_data = raw_data_relative
597 update_script_lines__
598
599 match = raw_data.keys.sort.grep(filename_re).first
600 return nil unless match
601
602 refine_coverage_info(@script_lines__[match], raw_data[match])
603 end
604
605 # Execute the code in the given block, monitoring it in order to gather
606 # information about which code was executed.
607 def run_hooked; super end
608
609 # Start monitoring execution to gather code coverage and execution count
610 # information. Such data will be collected until #remove_hook is called.
611 #
612 # Use #run_hooked instead if possible.
613 def install_hook; super end
614
615 # Stop collecting code coverage and execution count information.
616 # #remove_hook will also stop collecting info if it is run inside a
617 # #run_hooked block.
618 def remove_hook; super end
619
620 # Remove the data collected so far. The coverage and execution count
621 # "history" will be erased, and further collection will start from scratch:
622 # no code is considered executed, and therefore all execution counts are 0.
623 # Right after #reset, #analyzed_files will return an empty array, and
624 # #data(filename) will return nil.
625 def reset; super end
626
627 def dump_coverage_info(formatters) # :nodoc:
628 update_script_lines__
629 raw_data_relative.each do |file, lines|
630 next if @script_lines__.has_key?(file) == false
631 lines = @script_lines__[file]
632 raw_coverage_array = raw_data_relative[file]
633
634 line_info, marked_info,
635 count_info = refine_coverage_info(lines, raw_coverage_array)
636 formatters.each do |formatter|
637 formatter.add_file(file, line_info, marked_info, count_info)
638 end
639 end
640 formatters.each{|formatter| formatter.execute}
641 end
642
643 private
644
645 def data_default; {} end
646
647 def raw_data_absolute
648 Rcov::RCOV__.generate_coverage_info
649 end
650
651 def aggregate_data(aggregated_data, delta)
652 delta.each_pair do |file, cov_arr|
653 dest = (aggregated_data[file] ||= Array.new(cov_arr.size, 0))
654 cov_arr.each_with_index{|x,i| dest[i] += x}
655 end
656 end
657
658 def compute_raw_data_difference(first, last)
659 difference = {}
660 last.each_pair do |fname, cov_arr|
661 unless first.has_key?(fname)
662 difference[fname] = cov_arr.clone
663 else
664 orig_arr = first[fname]
665 diff_arr = Array.new(cov_arr.size, 0)
666 changed = false
667 cov_arr.each_with_index do |x, i|
668 diff_arr[i] = diff = (x || 0) - (orig_arr[i] || 0)
669 changed = true if diff != 0
670 end
671 difference[fname] = diff_arr if changed
672 end
673 end
674 difference
675 end
676
677
678 def refine_coverage_info(lines, covers)
679 marked_info = []
680 count_info = []
681 lines.size.times do |i|
682 c = covers[i]
683 marked_info << ((c && c > 0) ? true : false)
684 count_info << (c || 0)
685 end
686
687 script_lines_workaround(lines, marked_info, count_info)
688 end
689
690 # Try to detect repeated data, based on observed repetitions in line_info:
691 # this is a workaround for SCRIPT_LINES__[filename] including as many copies
692 # of the file as the number of times it was parsed.
693 def script_lines_workaround(line_info, coverage_info, count_info)
694 is_repeated = lambda do |div|
695 n = line_info.size / div
696 break false unless line_info.size % div == 0 && n > 1
697 different = false
698 n.times do |i|
699 if (0...div).map{|j| line_info[i+j*n]}.uniq.size != 1
700 different = true
701 break
702 end
703 end
704
705 ! different
706 end
707
708 factors = braindead_factorize(line_info.size)
709 factors.each do |n|
710 if is_repeated[n]
711 line_info = line_info[0, line_info.size / n]
712 coverage_info = coverage_info[0, coverage_info.size / n]
713 count_info = count_info[0, count_info.size / n]
714 end
715 end if factors.size > 1 # don't even try if it's prime
716
717 [line_info, coverage_info, count_info]
718 end
719
720 def braindead_factorize(num)
721 return [0] if num == 0
722 return [-1] + braindead_factorize(-num) if num < 0
723 factors = []
724 while num % 2 == 0
725 factors << 2
726 num /= 2
727 end
728 size = num
729 n = 3
730 max = Math.sqrt(num)
731 while n <= max && n <= size
732 while size % n == 0
733 size /= n
734 factors << n
735 end
736 n += 2
737 end
738 factors << size if size != 1
739 factors
740 end
741
742 def update_script_lines__
743 @script_lines__ = @script_lines__.merge(SCRIPT_LINES__)
744 end
745
746 public
747 def marshal_dump # :nodoc:
748 # @script_lines__ is updated just before serialization so as to avoid
749 # missing files in SCRIPT_LINES__
750 ivs = {}
751 update_script_lines__
752 instance_variables.each{|iv| ivs[iv] = instance_variable_get(iv)}
753 ivs
754 end
755
756 def marshal_load(ivs) # :nodoc:
757 ivs.each_pair{|iv, val| instance_variable_set(iv, val)}
758 end
759
760 end # CodeCoverageAnalyzer
761
762 # A CallSiteAnalyzer can be used to obtain information about:
763 # * where a method is defined ("+defsite+")
764 # * where a method was called from ("+callsite+")
765 #
766 # == Example
767 # <tt>example.rb</tt>:
768 # class X
769 # def f1; f2 end
770 # def f2; 1 + 1 end
771 # def f3; f1 end
772 # end
773 #
774 # analyzer = Rcov::CallSiteAnalyzer.new
775 # x = X.new
776 # analyzer.run_hooked do
777 # x.f1
778 # end
779 # # ....
780 #
781 # analyzer.run_hooked do
782 # x.f3
783 # # the information generated in this run is aggregated
784 # # to the previously recorded one
785 # end
786 #
787 # analyzer.analyzed_classes # => ["X", ... ]
788 # analyzer.methods_for_class("X") # => ["f1", "f2", "f3"]
789 # analyzer.defsite("X#f1") # => DefSite object
790 # analyzer.callsites("X#f2") # => hash with CallSite => count
791 # # associations
792 # defsite = analyzer.defsite("X#f1")
793 # defsite.file # => "example.rb"
794 # defsite.line # => 2
795 #
796 # You can have several CallSiteAnalyzer objects at a time, and it is
797 # possible to nest the #run_hooked / #install_hook/#remove_hook blocks: each
798 # analyzer will manage its data separately. Note however that no special
799 # provision is taken to ignore code executed "inside" the CallSiteAnalyzer
800 # class.
801 #
802 # +defsite+ information is only available for methods that were called under
803 # the inspection of the CallSiteAnalyzer, i.o.w. you will only have +defsite+
804 # information for those methods for which callsite information is
805 # available.
806 class CallSiteAnalyzer < DifferentialAnalyzer
807 # A method definition site.
808 class DefSite < Struct.new(:file, :line)
809 end
810
811 # Object representing a method call site.
812 # It corresponds to a part of the callstack starting from the context that
813 # called the method.
814 class CallSite < Struct.new(:backtrace)
815 # The depth of a CallSite is the number of stack frames
816 # whose information is included in the CallSite object.
817 def depth
818 backtrace.size
819 end
820
821 # File where the method call originated.
822 # Might return +nil+ or "" if it is not meaningful (C extensions, etc).
823 def file(level = 0)
824 stack_frame = backtrace[level]
825 stack_frame ? stack_frame[2] : nil
826 end
827
828 # Line where the method call originated.
829 # Might return +nil+ or 0 if it is not meaningful (C extensions, etc).
830 def line(level = 0)
831 stack_frame = backtrace[level]
832 stack_frame ? stack_frame[3] : nil
833 end
834
835 # Name of the method where the call originated.
836 # Returns +nil+ if the call originated in +toplevel+.
837 # Might return +nil+ if it could not be determined.
838 def calling_method(level = 0)
839 stack_frame = backtrace[level]
840 stack_frame ? stack_frame[1] : nil
841 end
842
843 # Name of the class holding the method where the call originated.
844 # Might return +nil+ if it could not be determined.
845 def calling_class(level = 0)
846 stack_frame = backtrace[level]
847 stack_frame ? stack_frame[0] : nil
848 end
849 end
850
851 @hook_level = 0
852 # defined this way instead of attr_accessor so that it's covered
853 def self.hook_level # :nodoc:
854 @hook_level
855 end
856 def self.hook_level=(x) # :nodoc:
857 @hook_level = x
858 end
859
860 def initialize
861 super(:install_callsite_hook, :remove_callsite_hook,
862 :reset_callsite)
863 end
864
865 # Classes whose methods have been called.
866 # Returns an array of strings describing the classes (just klass.to_s for
867 # each of them). Singleton classes are rendered as:
868 # #<Class:MyNamespace::MyClass>
869 def analyzed_classes
870 raw_data_relative.first.keys.map{|klass, meth| klass}.uniq.sort
871 end
872
873 # Methods that were called for the given class. See #analyzed_classes for
874 # the notation used for singleton classes.
875 # Returns an array of strings or +nil+
876 def methods_for_class(classname)
877 a = raw_data_relative.first.keys.select{|kl,_| kl == classname}.map{|_,meth| meth}.sort
878 a.empty? ? nil : a
879 end
880 alias_method :analyzed_methods, :methods_for_class
881
882 # Returns a hash with <tt>CallSite => call count</tt> associations or +nil+
883 # Can be called in two ways:
884 # analyzer.callsites("Foo#f1") # instance method
885 # analyzer.callsites("Foo.g1") # singleton method of the class
886 # or
887 # analyzer.callsites("Foo", "f1")
888 # analyzer.callsites("#<class:Foo>", "g1")
889 def callsites(classname_or_fullname, methodname = nil)
890 rawsites = raw_data_relative.first[expand_name(classname_or_fullname, methodname)]
891 return nil unless rawsites
892 ret = {}
893 # could be a job for inject but it's slow and I don't mind the extra loc
894 rawsites.each_pair do |backtrace, count|
895 ret[CallSite.new(backtrace)] = count
896 end
897 ret
898 end
899
900 # Returns a DefSite object corresponding to the given method
901 # Can be called in two ways:
902 # analyzer.defsite("Foo#f1") # instance method
903 # analyzer.defsite("Foo.g1") # singleton method of the class
904 # or
905 # analyzer.defsite("Foo", "f1")
906 # analyzer.defsite("#<class:Foo>", "g1")
907 def defsite(classname_or_fullname, methodname = nil)
908 file, line = raw_data_relative[1][expand_name(classname_or_fullname, methodname)]
909 return nil unless file && line
910 DefSite.new(file, line)
911 end
912
913 private
914
915 def expand_name(classname_or_fullname, methodname = nil)
916 if methodname.nil?
917 case classname_or_fullname
918 when /(.*)#(.*)/: classname, methodname = $1, $2
919 when /(.*)\.(.*)/: classname, methodname = "#<Class:#{$1}>", $2
920 else
921 raise ArgumentError, "Incorrect method name"
922 end
923
924 return [classname, methodname]
925 end
926
927 [classname_or_fullname, methodname]
928 end
929
930 def data_default; [{}, {}] end
931
932 def raw_data_absolute
933 raw, method_def_site = RCOV__.generate_callsite_info
934 ret1 = {}
935 ret2 = {}
936 raw.each_pair do |(klass, method), hash|
937 begin
938 key = [klass.to_s, method.to_s]
939 ret1[key] = hash.clone #Marshal.load(Marshal.dump(hash))
940 ret2[key] = method_def_site[[klass, method]]
941 #rescue Exception
942 end
943 end
944
945 [ret1, ret2]
946 end
947
948 def aggregate_data(aggregated_data, delta)
949 callsites1, defsites1 = aggregated_data
950 callsites2, defsites2 = delta
951
952 callsites2.each_pair do |(klass, method), hash|
953 dest_hash = (callsites1[[klass, method]] ||= {})
954 hash.each_pair do |callsite, count|
955 dest_hash[callsite] ||= 0
956 dest_hash[callsite] += count
957 end
958 end
959
960 defsites1.update(defsites2)
961 end
962
963 def compute_raw_data_difference(first, last)
964 difference = {}
965 default = Hash.new(0)
966
967 callsites1, defsites1 = *first
968 callsites2, defsites2 = *last
969
970 callsites2.each_pair do |(klass, method), hash|
971 old_hash = callsites1[[klass, method]] || default
972 hash.each_pair do |callsite, count|
973 diff = hash[callsite] - (old_hash[callsite] || 0)
974 if diff > 0
975 difference[[klass, method]] ||= {}
976 difference[[klass, method]][callsite] = diff
977 end
978 end
979 end
980
981 [difference, defsites1.update(defsites2)]
982 end
983
984 end
985
986 end # Rcov
987
988 # vi: set sw=2:
Generated using the rcov code coverage analysis tool for Ruby
version <IP_ADDRESS>.


Particle Maze
Particle Maze is a randomnly generated Maze (using DFS) from particles. The Maze is solved using A* Algorithms between two node (start & end).
Technology used:
Javascript
Webgl (threejs Lib)
Restart
Github Repo


Link to CSS Title
Image
Rebecca Paige
Gamer, coder, comic book enthusiast
Dev Bootcamp Mudturtles - 2014
Nav
About me


Hi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther you Hi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther youHi, I would like to inquire...
+Read MoreHi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther you Hi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther youHi, I would like to inquire...
+Read MoreHi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther you Hi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther youHi, I would like to inquire...
+Read MoreHi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther you Hi, I would like to inquire about your new work. Its andndn and an d I the reire ai ia. THat is the the way ther youHi, I would like to inquire...
+Read More


new TilemapLayer(game, tilemap, index, width, height)
A Tilemap Layer is a set of map data combined with a Tileset in order to render that data to the game.
Parameters:
| Name | Type | Description |
|---|---|---|
game |
Phaser.Game | Game reference to the currently running game. |
tilemap |
Phaser.Tilemap | The tilemap to which this layer belongs. |
index |
number | The layer index within the map that this TilemapLayer represents. |
width |
number | Width of the renderable area of the layer. |
height |
number | Height of the renderable area of the layer. |
- Source:
Members
-
baseTexture
-
- Source:
Properties:
Name Type Description baseTexture
PIXI.BaseTexture Required Pixi var.
-
cameraOffset
-
- Source:
Properties:
Name Type Description cameraOffset
Phaser.Point If this object is fixed to the camera then use this Point to specify how far away from the Camera x/y it's rendered.
-
canvas
-
- Source:
Properties:
Name Type Description canvas
HTMLCanvasElement The canvas to which this TilemapLayer draws.
-
collisionHeight
-
- Source:
Properties:
Name Type Description collisionHeight
number The height of the collision tiles.
-
collisionWidth
-
- Source:
Properties:
Name Type Description collisionWidth
number The width of the collision tiles.
-
context
-
- Source:
Properties:
Name Type Description context
CanvasRenderingContext2D The 2d context of the canvas.
-
debug
-
- Default Value:
- false
- Source:
Properties:
Name Type Description debug
boolean If set to true the collideable tile edges path will be rendered. Only works when game is running in Phaser.CANVAS mode.
-
debugAlpha
-
- Default Value:
- 0.5
- Source:
Properties:
Name Type Description debugAlpha
number If debug is true then the tileset is rendered with this alpha level, to make the tile edges clearer.
-
debugCallbackColor
-
- Default Value:
- "rgba(255, 0, 0, 1)"
- Source:
Properties:
Name Type Description debugCallbackColor
string If debug is true this is the color used to outline the edges of tiles that have collision callbacks. Provide in hex or rgb/rgba string format.
-
debugColor
-
- Default Value:
- "rgba(0, 255, 0, 1)"
- Source:
Properties:
Name Type Description debugColor
string If debug is true this is the color used to outline the edges of collidable tiles. Provide in hex or rgb/rgba string format.
-
debugFill
-
- Default Value:
- false
- Source:
Properties:
Name Type Description debugFill
boolean If true the debug tiles are filled with debugFillColor AND stroked around.
-
debugFillColor
-
- Default Value:
- "rgba(0, 255, 0, 0.2)"
- Source:
Properties:
Name Type Description debugFillColor
string If debugFill is true this is the color used to fill the tiles. Provide in hex or rgb/rgba string format.
-
dirty
-
- Source:
Properties:
Name Type Description dirty
boolean Flag controlling when to re-render the layer.
-
fixedToCamera
-
An object that is fixed to the camera ignores the position of any ancestors in the display list and uses its x/y coordinates as offsets from the top left of the camera.
- Default Value:
- true
- Source:
Properties:
Name Type Description fixedToCamera
boolean Fixes this object to the Camera.
-
game
-
- Source:
Properties:
Name Type Description game
Phaser.Game A reference to the currently running Game.
-
index
-
- Source:
Properties:
Name Type Description index
number The index of this layer within the Tilemap.
-
layer
-
- Source:
Properties:
Name Type Description layer
object The layer object within the Tilemap that this layer represents.
-
map
-
- Source:
Properties:
Name Type Description map
Phaser.Tilemap The Tilemap to which this layer is bound.
-
name
-
- Source:
Properties:
Name Type Description name
string The name of the layer.
-
rayStepRate
-
- Default Value:
- 4
- Source:
Properties:
Name Type Description rayStepRate
number When ray-casting against tiles this is the number of steps it will jump. For larger tile sizes you can increase this to improve performance.
-
scrollFactorX
-
- Default Value:
- 1
- Source:
Properties:
Name Type Description scrollFactorX
number speed at which this layer scrolls horizontally, relative to the camera (e.g. scrollFactorX of 0.5 scrolls half as quickly as the 'normal' camera-locked layers do)
-
scrollFactorY
-
- Default Value:
- 1
- Source:
Properties:
Name Type Description scrollFactorY
number speed at which this layer scrolls vertically, relative to the camera (e.g. scrollFactorY of 0.5 scrolls half as quickly as the 'normal' camera-locked layers do)
-
scrollX
-
- Source:
Properties:
Name Type Description scrollX
number Scrolls the map horizontally or returns the current x position.
-
scrollY
-
- Source:
Properties:
Name Type Description scrollY
number Scrolls the map vertically or returns the current y position.
-
texture
-
- Source:
Properties:
Name Type Description texture
PIXI.Texture Required Pixi var.
-
textureFrame
-
- Source:
Properties:
Name Type Description textureFrame
Phaser.Frame Dimensions of the renderable area.
-
tileColor
-
- Default Value:
- "rgb(255, 255, 255)"
- Source:
Properties:
Name Type Description tileColor
string If no tileset is given the tiles will be rendered as rectangles in this color. Provide in hex or rgb/rgba string format.
-
type
-
- Source:
Properties:
Name Type Description type
number The const type of this object.
Methods
-
getRayCastTiles(line, stepRate, collides, interestingFace) → {array.<Phaser.Tile>}
-
Gets all tiles that intersect with the given line.
Parameters:
Name Type Argument Default Description line
Phaser.Line The line used to determine which tiles to return.
stepRate
number <optional>
How many steps through the ray will we check? If undefined or null it uses TilemapLayer.rayStepRate.
collides
boolean <optional>
false If true only return tiles that collide on one or more faces.
interestingFace
boolean <optional>
false If true only return tiles that have interesting faces.
- Source:
Returns:
An array of Phaser.Tiles.
- Type
- array.<Phaser.Tile>
-
getTiles(x, y, width, height, collides, interestingFace) → {array.<Phaser.Tile>}
-
Get all tiles that exist within the given area, defined by the top-left corner, width and height. Values given are in pixels, not tiles.
Parameters:
Name Type Argument Default Description x
number X position of the top left corner.
y
number Y position of the top left corner.
width
number Width of the area to get.
height
number Height of the area to get.
collides
boolean <optional>
false If true only return tiles that collide on one or more faces.
interestingFace
boolean <optional>
false If true only return tiles that have interesting faces.
- Source:
Returns:
An array of Phaser.Tiles.
- Type
- array.<Phaser.Tile>
-
getTileX(x) → {Phaser.Tile}
-
Convert a pixel value to a tile coordinate.
Parameters:
Name Type Description x
number X position of the point in target tile.
- Source:
Returns:
The tile with specific properties.
- Type
- Phaser.Tile
-
getTileXY(x, y, point) → {Phaser.Point|object}
-
Convert a pixel value to a tile coordinate.
Parameters:
Name Type Description x
number X position of the point in target tile.
y
number Y position of the point in target tile.
point
Phaser.Point | object The Point object to set the x and y values on.
- Source:
Returns:
A Point object with its x and y properties set.
- Type
- Phaser.Point | object
-
getTileY(y) → {Phaser.Tile}
-
Convert a pixel value to a tile coordinate.
Parameters:
Name Type Description y
number Y position of the point in target tile.
- Source:
Returns:
The tile with specific properties.
- Type
- Phaser.Tile
-
postUpdate()
-
Automatically called by World.postUpdate. Handles cache updates.
- Source:
-
render()
-
Renders the tiles to the layer canvas and pushes to the display.
- Source:
-
renderDebug()
-
Renders a collision debug overlay on-top of the canvas. Called automatically by render when debug = true.
- Source:
-
resizeWorld()
-
Sets the world size to match the size of this layer.
- Source:
-
updateMax()
-
Internal function to update maximum values.
- Source:


0">
Your next payment of ${{customer.account_balance}} is due on {{subscription.current_period_end*1000 | date: constants.DateYearFormat}}.
0">
You have {{creditCards.length}} credit card on file.
- {{creditCard.brand}} that ends in {{creditCard.last4}}
Please note that we do NOT store your credit card information - everything is done securely through our payment processor Stripe.


Hot-keys on this page
n s m x c change column sorting
| Module | statements | missing | excluded | coverage |
|---|---|---|---|---|
| Total | 2038 | 263 | 0 | 87% |
| lib/agents/__init__ | 2 | 0 | 0 | 100% |
| lib/agents/base_agent | 31 | 9 | 0 | 71% |
| lib/agents/ec2_agent | 229 | 53 | 0 | 77% |
| lib/agents/euca_agent | 64 | 32 | 0 | 50% |
| lib/agents/factory | 11 | 1 | 0 | 91% |
| lib/appcontroller_client | 83 | 15 | 0 | 82% |
| lib/appengine_helper | 48 | 2 | 0 | 96% |
| lib/appscale | 211 | 26 | 0 | 88% |
| lib/appscale_logger | 27 | 2 | 0 | 93% |
| lib/appscale_tools | 197 | 20 | 0 | 90% |
| lib/custom_exceptions | 16 | 0 | 0 | 100% |
| lib/local_state | 231 | 14 | 0 | 94% |
| lib/node_layout | 414 | 47 | 0 | 89% |
| lib/parse_args | 168 | 15 | 0 | 91% |
| lib/remote_helper | 227 | 11 | 0 | 95% |
| lib/user_app_client | 79 | 16 | 0 | 80% |


Plato on Github
Report Home
src\ng\animate.js
Maintainability
72.36
Lines of code
590
Difficulty
48.69
Estimated Errors
2.49
Function weight
By Complexity
By SLOC
'use strict'; var $animateMinErr = minErr('$animate'); var ELEMENT_NODE = 1; var NG_ANIMATE_CLASSNAME = 'ng-animate'; function mergeClasses(a,b) { if (!a && !b) return ''; if (!a) return b; if (!b) return a; if (isArray(a)) a = a.join(' '); if (isArray(b)) b = b.join(' '); return a + ' ' + b; } function extractElementNode(element) { for (var i = 0; i < element.length; i++) { var elm = element[i]; if (elm.nodeType === ELEMENT_NODE) { return elm; } } } function splitClasses(classes) { if (isString(classes)) { classes = classes.split(' '); } // Use createMap() to prevent class assumptions involving property names in // Object.prototype var obj = createMap(); forEach(classes, function(klass) { // sometimes the split leaves empty string values // incase extra spaces were applied to the options if (klass.length) { obj[klass] = true; } }); return obj; } // if any other type of options value besides an Object value is // passed into the $animate.method() animation then this helper code // will be run which will ignore it. While this patch is not the // greatest solution to this, a lot of existing plugins depend on // $animate to either call the callback (< 1.2) or return a promise // that can be changed. This helper function ensures that the options // are wiped clean incase a callback function is provided. function prepareAnimateOptions(options) { return isObject(options) ? options : {}; } var $$CoreAnimateRunnerProvider = function() { this.$get = ['$q', '$$rAF', function($q, $$rAF) { function AnimateRunner() {} AnimateRunner.all = noop; AnimateRunner.chain = noop; AnimateRunner.prototype = { end: noop, cancel: noop, resume: noop, pause: noop, complete: noop, then: function(pass, fail) { return $q(function(resolve) { $$rAF(function() { resolve(); }); }).then(pass, fail); } }; return AnimateRunner; }]; }; // this is prefixed with Core since it conflicts with // the animateQueueProvider defined in ngAnimate/animateQueue.js var $$CoreAnimateQueueProvider = function() { var postDigestQueue = new HashMap(); var postDigestElements = []; this.$get = ['$$AnimateRunner', '$rootScope', function($$AnimateRunner, $rootScope) { return { enabled: noop, on: noop, off: noop, pin: noop, push: function(element, event, options, domOperation) { domOperation && domOperation(); options = options || {}; options.from && element.css(options.from); options.to && element.css(options.to); if (options.addClass || options.removeClass) { addRemoveClassesPostDigest(element, options.addClass, options.removeClass); } return new $$AnimateRunner(); // jshint ignore:line } }; function addRemoveClassesPostDigest(element, add, remove) { var data = postDigestQueue.get(element); var classVal; if (!data) { postDigestQueue.put(element, data = {}); postDigestElements.push(element); } if (add) { forEach(add.split(' '), function(className) { if (className) { data[className] = true; } }); } if (remove) { forEach(remove.split(' '), function(className) { if (className) { data[className] = false; } }); } if (postDigestElements.length > 1) return; $rootScope.$$postDigest(function() { forEach(postDigestElements, function(element) { var data = postDigestQueue.get(element); if (data) { var existing = splitClasses(element.attr('class')); var toAdd = ''; var toRemove = ''; forEach(data, function(status, className) { var hasClass = !!existing[className]; if (status !== hasClass) { if (status) { toAdd += (toAdd.length ? ' ' : '') + className; } else { toRemove += (toRemove.length ? ' ' : '') + className; } } }); forEach(element, function(elm) { toAdd && jqLiteAddClass(elm, toAdd); toRemove && jqLiteRemoveClass(elm, toRemove); }); postDigestQueue.remove(element); } }); postDigestElements.length = 0; }); } }]; }; /** * @ngdoc provider * @name $animateProvider * * @description * Default implementation of $animate that doesn't perform any animations, instead just * synchronously performs DOM updates and resolves the returned runner promise. * * In order to enable animations the `ngAnimate` module has to be loaded. * * To see the functional implementation check out `src/ngAnimate/animate.js`. */ var $AnimateProvider = ['$provide', function($provide) { var provider = this; this.$$registeredAnimations = Object.create(null); /** * @ngdoc method * @name $animateProvider#register * * @description * Registers a new injectable animation factory function. The factory function produces the * animation object which contains callback functions for each event that is expected to be * animated. * * * `eventFn`: `function(element, ... , doneFunction, options)` * The element to animate, the `doneFunction` and the options fed into the animation. Depending * on the type of animation additional arguments will be injected into the animation function. The * list below explains the function signatures for the different animation methods: * * - setClass: function(element, addedClasses, removedClasses, doneFunction, options) * - addClass: function(element, addedClasses, doneFunction, options) * - removeClass: function(element, removedClasses, doneFunction, options) * - enter, leave, move: function(element, doneFunction, options) * - animate: function(element, fromStyles, toStyles, doneFunction, options) * * Make sure to trigger the `doneFunction` once the animation is fully complete. * * ```js * return { * //enter, leave, move signature * eventFn : function(element, done, options) { * //code to run the animation * //once complete, then run done() * return function endFunction(wasCancelled) { * //code to cancel the animation * } * } * } * ``` * * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to). * @param {Function} factory The factory function that will be executed to return the animation * object. */ this.register = function(name, factory) { if (name && name.charAt(0) !== '.') { throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name); } var key = name + '-animation'; provider.$$registeredAnimations[name.substr(1)] = key; $provide.factory(key, factory); }; /** * @ngdoc method * @name $animateProvider#classNameFilter * * @description * Sets and/or returns the CSS class regular expression that is checked when performing * an animation. Upon bootstrap the classNameFilter value is not set at all and will * therefore enable $animate to attempt to perform an animation on any element that is triggered. * When setting the `classNameFilter` value, animations will only be performed on elements * that successfully match the filter expression. This in turn can boost performance * for low-powered devices as well as applications containing a lot of structural operations. * @param {RegExp=} expression The className expression which will be checked against all animations * @return {RegExp} The current CSS className expression value. If null then there is no expression value */ this.classNameFilter = function(expression) { if (arguments.length === 1) { this.$$classNameFilter = (expression instanceof RegExp) ? expression : null; if (this.$$classNameFilter) { var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)"); if (reservedRegex.test(this.$$classNameFilter.toString())) { throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME); } } } return this.$$classNameFilter; }; this.$get = ['$$animateQueue', function($$animateQueue) { function domInsert(element, parentElement, afterElement) { // if for some reason the previous element was removed // from the dom sometime before this code runs then let's // just stick to using the parent element as the anchor if (afterElement) { var afterNode = extractElementNode(afterElement); if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { afterElement = null; } } afterElement ? afterElement.after(element) : parentElement.prepend(element); } /** * @ngdoc service * @name $animate * @description The $animate service exposes a series of DOM utility methods that provide support * for animation hooks. The default behavior is the application of DOM operations, however, * when an animation is detected (and animations are enabled), $animate will do the heavy lifting * to ensure that animation runs with the triggered DOM operation. * * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't * included and only when it is active then the animation hooks that `$animate` triggers will be * functional. Once active then all structural `ng-` directives will trigger animations as they perform * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`, * `ngShow`, `ngHide` and `ngMessages` also provide support for animations. * * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives. * * To learn more about enabling animation support, click here to visit the * {@link ngAnimate ngAnimate module page}. */ return { // we don't call it directly since non-existant arguments may // be interpreted as null within the sub enabled function /** * * @ngdoc method * @name $animate#on * @kind function * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...) * has fired on the given element or among any of its children. Once the listener is fired, the provided callback * is fired with the following params: * * ```js * $animate.on('enter', container, * function callback(element, phase) { * // cool we detected an enter animation within the container * } * ); * ``` * * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...) * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself * as well as among its children * @param {Function} callback the callback function that will be fired when the listener is triggered * * The arguments present in the callback function are: * * `element` - The captured DOM element that the animation was fired on. * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends). */ on: $$animateQueue.on, /** * * @ngdoc method * @name $animate#off * @kind function * @description Deregisters an event listener based on the event which has been associated with the provided element. This method * can be used in three different ways depending on the arguments: * * ```js * // remove all the animation event listeners listening for `enter` * $animate.off('enter'); * * // remove all the animation event listeners listening for `enter` on the given element and its children * $animate.off('enter', container); * * // remove the event listener function provided by `listenerFn` that is set * // to listen for `enter` on the given `element` as well as its children * $animate.off('enter', container, callback); * ``` * * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...) * @param {DOMElement=} container the container element the event listener was placed on * @param {Function=} callback the callback function that was registered as the listener */ off: $$animateQueue.off, /** * @ngdoc method * @name $animate#pin * @kind function * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the * element despite being outside the realm of the application or within another application. Say for example if the application * was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association. * * Note that this feature is only active when the `ngAnimate` module is used. * * @param {DOMElement} element the external element that will be pinned * @param {DOMElement} parentElement the host parent element that will be associated with the external element */ pin: $$animateQueue.pin, /** * * @ngdoc method * @name $animate#enabled * @kind function * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This * function can be called in four ways: * * ```js * // returns true or false * $animate.enabled(); * * // changes the enabled state for all animations * $animate.enabled(false); * $animate.enabled(true); * * // returns true or false if animations are enabled for an element * $animate.enabled(element); * * // changes the enabled state for an element and its children * $animate.enabled(element, true); * $animate.enabled(element, false); * ``` * * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state * @param {boolean=} enabled whether or not the animations will be enabled for the element * * @return {boolean} whether or not animations are enabled */ enabled: $$animateQueue.enabled, /** * @ngdoc method * @name $animate#cancel * @kind function * @description Cancels the provided animation. * * @param {Promise} animationPromise The animation promise that is returned when an animation is started. */ cancel: function(runner) { runner.end && runner.end(); }, /** * * @ngdoc method * @name $animate#enter * @kind function * @description Inserts the element into the DOM either after the `after` element (if provided) or * as the first child within the `parent` element and then triggers an animation. * A promise is returned that will be resolved during the next digest once the animation * has completed. * * @param {DOMElement} element the element which will be inserted into the DOM * @param {DOMElement} parent the parent element which will append the element as * a child (so long as the after element is not present) * @param {DOMElement=} after the sibling element after which the element will be appended * @param {object=} options an optional collection of options/styles that will be applied to the element * * @return {Promise} the animation callback promise */ enter: function(element, parent, after, options) { parent = parent && jqLite(parent); after = after && jqLite(after); parent = parent || after.parent(); domInsert(element, parent, after); return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options)); }, /** * * @ngdoc method * @name $animate#move * @kind function * @description Inserts (moves) the element into its new position in the DOM either after * the `after` element (if provided) or as the first child within the `parent` element * and then triggers an animation. A promise is returned that will be resolved * during the next digest once the animation has completed. * * @param {DOMElement} element the element which will be moved into the new DOM position * @param {DOMElement} parent the parent element which will append the element as * a child (so long as the after element is not present) * @param {DOMElement=} after the sibling element after which the element will be appended * @param {object=} options an optional collection of options/styles that will be applied to the element * * @return {Promise} the animation callback promise */ move: function(element, parent, after, options) { parent = parent && jqLite(parent); after = after && jqLite(after); parent = parent || after.parent(); domInsert(element, parent, after); return $$animateQueue.push(element, 'move', prepareAnimateOptions(options)); }, /** * @ngdoc method * @name $animate#leave * @kind function * @description Triggers an animation and then removes the element from the DOM. * When the function is called a promise is returned that will be resolved during the next * digest once the animation has completed. * * @param {DOMElement} element the element which will be removed from the DOM * @param {object=} options an optional collection of options/styles that will be applied to the element * * @return {Promise} the animation callback promise */ leave: function(element, options) { return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() { element.remove(); }); }, /** * @ngdoc method * @name $animate#addClass * @kind function * * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon * execution, the addClass operation will only be handled after the next digest and it will not trigger an * animation if element already contains the CSS class or if the class is removed at a later step. * Note that class-based animations are treated differently compared to structural animations * (like enter, move and leave) since the CSS classes may be added/removed at different points * depending if CSS or JavaScript animations are used. * * @param {DOMElement} element the element which the CSS classes will be applied to * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces) * @param {object=} options an optional collection of options/styles that will be applied to the element * * @return {Promise} the animation callback promise */ addClass: function(element, className, options) { options = prepareAnimateOptions(options); options.addClass = mergeClasses(options.addclass, className); return $$animateQueue.push(element, 'addClass', options); }, /** * @ngdoc method * @name $animate#removeClass * @kind function * * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon * execution, the removeClass operation will only be handled after the next digest and it will not trigger an * animation if element does not contain the CSS class or if the class is added at a later step. * Note that class-based animations are treated differently compared to structural animations * (like enter, move and leave) since the CSS classes may be added/removed at different points * depending if CSS or JavaScript animations are used. * * @param {DOMElement} element the element which the CSS classes will be applied to * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces) * @param {object=} options an optional collection of options/styles that will be applied to the element * * @return {Promise} the animation callback promise */ removeClass: function(element, className, options) { options = prepareAnimateOptions(options); options.removeClass = mergeClasses(options.removeClass, className); return $$animateQueue.push(element, 'removeClass', options); }, /** * @ngdoc method * @name $animate#setClass * @kind function * * @description Performs both the addition and removal of a CSS classes on an element and (during the process) * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has * passed. Note that class-based animations are treated differently compared to structural animations * (like enter, move and leave) since the CSS classes may be added/removed at different points * depending if CSS or JavaScript animations are used. * * @param {DOMElement} element the element which the CSS classes will be applied to * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces) * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces) * @param {object=} options an optional collection of options/styles that will be applied to the element * * @return {Promise} the animation callback promise */ setClass: function(element, add, remove, options) { options = prepareAnimateOptions(options); options.addClass = mergeClasses(options.addClass, add); options.removeClass = mergeClasses(options.removeClass, remove); return $$animateQueue.push(element, 'setClass', options); }, /** * @ngdoc method * @name $animate#animate * @kind function * * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take * on the provided styles. For example, if a transition animation is set for the given className then the provided from and * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter). * * @param {DOMElement} element the element which the CSS styles will be applied to * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation. * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element. * (Note that if no animation is detected then this value will not be appplied to the element.) * @param {object=} options an optional collection of options/styles that will be applied to the element * * @return {Promise} the animation callback promise */ animate: function(element, from, to, className, options) { options = prepareAnimateOptions(options); options.from = options.from ? extend(options.from, from) : from; options.to = options.to ? extend(options.to, to) : to; className = className || 'ng-inline-animate'; options.tempClasses = mergeClasses(options.tempClasses, className); return $$animateQueue.push(element, 'animate', options); } }; }]; }];