|
Ocular Engine
|
#include <MeshResourceLoader_PLY.hpp>
Protected Member Functions | |
| virtual bool | readFile (Core::File const &file, std::vector< Graphics::Vertex > &vertices, std::vector< uint32_t > &indices, uint32_t &numVertices, uint32_t &numIndices, Math::Vector3f &min, Math::Vector3f &max) override |
| bool | parseHeader (std::ifstream &stream) |
| bool | parseElement (std::ifstream &stream, std::string &line, PLYParser **parser) |
| bool | parseElementNameAndCount (std::string const &line, PLYParser *parser) const |
| bool | parseProperty (std::string const &line, PLYElementParser *parser) const |
| bool | parsePropertyList (std::string const &line, PLYElementListParser *parser) const |
| bool | parseBody (std::ifstream &stream, std::vector< Graphics::Vertex > &vertices, std::vector< uint32_t > &indices, uint32_t &numVertices, uint32_t &numIndices, Math::Vector3f &min, Math::Vector3f &max) |
| bool | isValidPLYFile (std::ifstream &stream) const |
| bool | isComment (std::string const &line) const |
| bool | isElement (std::string const &line) const |
| bool | isElementList (std::string const &line) const |
| bool | isFormatASCII (std::string const &line) const |
| PLYPropertyType | toPropertyType (std::string const &str) const |
| PLYElementType | toElementType (std::string const &str) const |
| void | reserveVectorSpace (std::vector< Graphics::Vertex > &vertices, std::vector< uint32_t > &indices) const |
| Protected Member Functions inherited from Ocular::Graphics::MeshResourceLoader | |
| virtual bool | createResource (Core::Resource *&resource, Core::File const &file, std::vector< Graphics::Vertex > const &vertices, std::vector< uint32_t > const &indices, uint32_t numVertices, uint32_t numIndices, Math::Vector3f const &min, Math::Vector3f const &max) |
| Protected Member Functions inherited from Ocular::Core::AResourceLoader | |
| bool | isFileValid (Core::File const &file) const |
Additional Inherited Members | |
| Public Member Functions inherited from Ocular::Graphics::MeshResourceLoader | |
| MeshResourceLoader (std::string const &extension) | |
| virtual bool | loadResource (Core::Resource *&resource, Core::File const &file, std::string const &mappingName) override |
| Public Member Functions inherited from Ocular::Core::AResourceLoader | |
| AResourceLoader (std::string const &extension, ResourceType type) | |
| virtual std::string | getSupportedFileType () const |
| virtual bool | loadSubResource (Resource *&resource, File const &file, std::string const &mappingName) |
| virtual bool | exploreResource (File const &file) |
| ResourceType | getResourceType () const |
| Protected Attributes inherited from Ocular::Core::AResourceLoader | |
| std::string | m_SupportedExtension |
| ResourceType | m_Type |
Implementation of AResourceLoader that handles the loading of files with the '.ply' extension as meshes.
|
protected |
Header is split into the following pieces:
- Identifier - Element definition - End of header
In addition to this, any line of the file (including the header), may be a comment. A comment is any line that begins with 'comment'. Example:
comment This line is a comment
The identifier informs us that this is a PLY file and what type of PLY file. A file is marked as a PLY by having it's very first line be equal to 'ply'. The next line will then tell which of the following kinds of PLY files it is:
ASCII Binary (little endian) Binary (big endian)
So an identifier will look like:
ply format ascii 1.0
or
ply format binary_little_endian 1.0
etc.
The rest of the header is dedicated to defining the elements that make up the body of the PLY header. This can occur in one of two different ways. Either an element definition followed by a variable number of property definitions, or an element definition followed by a single property list.
The element definition also tells us what kind of element it is, and how many individual elements there are. Example:
element vertex 8 property float x property float y property float z element face 6 property list uchar int vertex_index
The above tells us there will be 8 vertex elements, each defined as (x, y, z). It will then be followed by 6 face elements, defined as a variable number of integer indices.
Finally, the end of the header is marked by 'end_header'. All together, a header may resemble:
ply format ascii 1.0 example A sample header element vertex 8 property float x property float y property float z element face 6 property list uchar int vertex_index end_header
It should be noted there are no limits to the number of elements or their properties. There is also no standard set of element types. But the following are generally accepted:
vertex face edge
Of which, we currently support vertex and face. Any unsupported or unknown element types will simply be skipped over while parsing the body.
See below for more information: http://paulbourke.net/dataformats/ply/
|
overrideprotectedvirtual |
Each MeshResourceLoader must provide a custom implementation for it's specific file type.
| [in] | file | Source file to read from. |
| [out] | vertices | Texture pixel data read in from the file. |
| [out] | indices | Width of the texture. |
| [out] | numVertices | Number of vertices in the mesh (depending on the loader implementation, this may not equal vertices.size()) |
| [out] | numIndices | Number of indices in the mesh (depending on the loader implementation, this may not equal indices.size()) |
| [out] | min | The minimum spatial point along the local axis among all vertices |
| [out] | max | The maximum spatial point along the local axis among all vertices |
Implements Ocular::Graphics::MeshResourceLoader.


Cards can be organized via Bootstrap's grid system or by using a couple handy helper classes included in crds-styles
. These helper classes help the columns wrap correctly even when they're different heights with a CSS clearfix solution.
To render cards in two columns wrap them with .row
and a .cards-2x
selector, like so...
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereUse the .cards-3x
selector to display 3 columns on desktop screens.
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereWant to display 4 columns on desktop screens? Just use the .cards-4x
selector...
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereBy default all of these classes display 1 column on mobile. If you want them to display 2x on the smallest screens use the .cards-2x-xs
selector...
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereBy default, card images will inherit height of the image added. This can result in a non-uniform layout. If you would like your card images to have a consistent height, apply the class .card-img-constrained
selector to the image(s). The example below shows the effect of these selectors.
.card-img-constrained
sets images to 200px in height, and crops and centers them.
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereSome quick example text to build on the card title and make up the bulk of the card's content.
Go somewhere


The diameter of the earth at the equator is about 12 756 kilometer.
About how many thousand kilometers is diameter of the Earth at the equator?
You can find the answer by rounding 12 756 to the nearest thousands.
Study the number line below.
To which number is 12 756 closer, 12 000 or 13 000?
Since 12 756 is closer to 13 000, you can say that 12 756 becomes 13 000 when rounded to the nearest thousands. Hence, the diameter of Earth at the equator is about 13 000 kilometers.
Here are the other examples. Study.
• Rule for rounding to the nearest Thousand
Look at the number in hundred’s place
For 0, 1, 2, 3, or 4 we round down
For 5, 6, 7, 8, or 9 we round up (that is add +1)
Examples:
Let’s round 17 389 to the nearest thousand.
Since the hundred place is 3, we round down.
So, we round 17 389 to 17000.
Let’s round 17 589 to the nearest thousand.
Since the thousand place is 5, we round up (that is add +1).
So, we round 17589 to 18 000.
• Rule for rounding to the nearest Ten Thousand
Look at the number in thousand’s place
For 0, 1, 2, 3, or 4 we round down
For 5, 6, 7, 8, or 9 we round up (that is add +1)
Examples:
Let’s Round 34 398 to the nearest ten thousand.
Since the hundred place is 3, we round down.
So, we round 34 389 to 34 000.
Let’s round 35 670 to the nearest ten thousand.
Since the thousand place is 5, we round up (that is add +1).
So, we round 35 670 to 36 000.
Round each number to the place value of the underlined digit.
1. 67 436 67 000
2. 34 673 30 000
3. 87 567 87 600
4. 82 652 80 000
5. 34 982 35 000


Pizza Pie!
Name:
Street Address:
Zip Code:
Select a size:
10-inch ($6.00)
12-inch ($8.00)
14-inch ($10.00)
16-inch ($12.00)
Choose your toppings on the right
Cheese
+$0.00
Is this for take out or delivery?
Take Out (+$0.00)
Delivery (+$3.00)
Add to Cart
Regular Toppings:
Bacon
Italian Sausage
Ground Beef
Ham
Pepperoni
Black Olives
Extra Cheese
Green Peppers
Jalapenos
Mushrooms
Onions
Pineapple
Spinach
Tomatoes
Premium Toppings:
Anchovies
Artichoke Hearts
Feta Cheese
Gorgonzola
Grilled Chicken
Kalamata Olives
Linguica
Roasted Peppers
Shaved Steak
My Shopping Cart:


--- title: articles description: software-development and computer-science articles. stylesheet: true sitemap: changefreq: weekly priority: 0.7 head: | --- [RSS] {% include tag_cloud.html %}


FIT1050 Lecture
10m - 11am
FIT1045 Lecture
1pm - 2pm
MAT1830 Tutorial
8:30am - 10am
FIT1045 Lecture
1pm - 2pm
FIT1047 Lecture
2pm - 3pm
FIT1045 Tutorial
3pm-5pm
Palendar
username here
Please enter the earliest and latest time you are willing to study.


Web hosting providers (FTP)
To upload a Jekyll site to a web host using FTP, simply run the JEKYLL_ENV=production jekyll build
command and copy the generated _site
folder to the root folder of your hosting account.
GitHub Pages
What are GitHub Pages? GitHub Pages are public web pages for users, organisations, and repositories, that are freely hosted on GitHub’s github.io
domain or on a custom domain name of your choice.
Full GitHub Pages deployment guide. We recommend you to read full GitHub Pages deployment guide here.
Set relative URLs properly! Please take a look at Relative URLs part of "Configuration" section before you deploy your site.
Build site with environment variable! Please build your site with proper environment variable before you deploy.
User and Organisation Pages
User and organisation pages live in a special GitHub repository dedicated to only the GitHub Pages files. This repository must be named after the account name. For example, @mojombo’s user page repository has the name mojombo.github.io
.
Content from the master
branch of your repository will be used to build and publish the GitHub Pages site, so make sure your _site
directory content is stored there.
Project Pages
Unlike user and organisation pages, project pages are kept in the same repository as the project they are for, except that the website content is stored in a specially named gh-pages
branch or in a /docs
folder on the master
branch.
Content from the gh-pages
branch or /docs
folder on your master
branch of your repository will be used to build and publish the GitHub Pages site, so make sure your _site
directory content is stored there.
Output will become available under a subpath of your user pages subdomain, such as username.github.io/project
(unless a custom domain is specified).
GitLab Pages
What are GitLab Pages? With GitLab Pages you can create static websites for your GitLab projects, groups, or user accounts. Connect as many customs domains as you like and bring your own TLS certificate to secure them.
Full GitLab Pages deployment guide. We recommend you to read full GitLab Pages deployment guide here.
Set relative URLs properly! Please take a look at Relative URLs part of "Configuration" section before you deploy your site.
Build site with environment variable! Please build your site with proper environment variable before you deploy.
User and Organisation Pages
User and organisation pages live in a special GitLab repository dedicated to only the GitLab Pages files. This repository must be named after the account name.
For example, if you create a project called john.gitlab.io
under your username, john
, your project URL will be https://gitlab.com/john/john.gitlab.io
. Once you enable GitLab Pages for your project, your website will be published under https://john.gitlab.io
.
Content from the gl-pages
branch of your repository will be used to build and publish the GitLab Pages site, so make sure your _site
directory content is stored there.
Project Pages
Unlike user and organisation pages, project pages are kept in the same repository as the project they are for, except that the website content is stored in a specially named gl-pages
branch.
Content from the gl-pages
branch of your repository will be used to build and publish the GitLab Pages site, so make sure your _site
directory content is stored there.
Output will become available under a subpath of your user pages subdomain, such as username.gitlab.io/project
(unless a custom domain is specified).


The Nexus is a sample application built with MongoDB, Express, Angular 2, and Node.js. It has been written by Fabian Vilers, and contributed by Sylvain Guerin. The source code is available on GitHub under the MIT License.
It also serves as a demo application for MEAN and Angular 2 trainings.
All information about characters of the game Heroes of the Storm is copyrighted to BLIZZARD ENTERTAINMENT, INC.


|
ArUco Unity
0.1.0
OpenCV's ArUco Marker Detection module adapted for Unity 5.
|
Manage OpenCV's camera parameters from a calibration. More...
Public Member Functions | |
| CameraParameters () | |
| Create an empty CameraParameters and set CalibrationDateTime to now. More... | |
| CameraParameters (int camerasNumber) | |
| void | SaveToXmlFile (string cameraParametersFilePath) |
| Save the camera parameters to a XML file. More... | |
Static Public Member Functions | |
| static CameraParameters | LoadFromXmlFile (string cameraParametersFilePath) |
| Create a new CameraParameters object from a previously saved camera parameters XML file. More... | |
Protected Member Functions | |
| void | UpdateCameraMatrixDerivedVariables () |
Protected Attributes | |
| int [] | imageHeight |
| Cv.Mat [] | cameraMatrix |
Properties | |
| DateTime | CalibrationDateTime [get, set] |
| The calibration date and time. More... | |
| int | CamerasNumber [get, protected set] |
| int [] | ImagesHeight [get, set] |
| The image height during the calibration. More... | |
| int [] | ImagesWidth [get, set] |
| The image width during the calibration. More... | |
| int | CalibrationFlags [get, set] |
| The calibration flags used. More... | |
| float | FixAspectRatioValue [get, set] |
| Non null if there is a fix image aspect ratio. More... | |
| double [] | ReprojectionError [get, set] |
| The average re-projection error of the calibration. More... | |
| Cv.Mat [] | CamerasMatrix [get, set] |
| The camera matrix of the calibration. More... | |
| Cv.TYPE | CameraMatrixType [get, set] |
| The camera matrix type of the calibration. Equals to CameraMatrix.Type() and automatically written when SaveToXmlFile(string) is called. More... | |
| double [][][] | CamerasMatrixValues [get, set] |
| The camera matrix values of the calibration. Equals to the CamerasMatrix content and automatically written when SaveToXmlFile(string) is called. More... | |
| Cv.Mat [] | DistCoeffs [get, set] |
| The distorsition coefficients of the calibration. More... | |
| Cv.TYPE | DistCoeffsType [get, set] |
| The distorsition coefficients type of the calibration. Equals to DistCoeffs.Type() and automatically written when SaveToXmlFile(string) is called. More... | |
| double [][][] | DistCoeffsValues [get, set] |
| The distorsition coefficients values of the calibration. Equals to the DistCoeffs content and automatically written when SaveToXmlFile(string) is called. More... | |
| Vector2 [] | CamerasFocalLength [get, protected set] |
| The camera focal length expressed in pixels coordinates. Equals to CameraMatrix.AtDouble(0, 0) on the x-axis and to to CameraMatrix.AtDouble(1, 1) on the y-axis. More... | |
| Vector2 [] | CamerasOpticalCenter [get, protected set] |
| The camera optical center expressed in pixels coordinates. Equals to CameraMatrix.AtDouble(0, 2) on the x-axis and to CameraMatrix.AtDouble(1, 2) on the y-axis. More... | |
| Vector3 [] | OpticalCenters [get, protected set] |
| The camera optical center in the Unity world space. More... | |
| string | FilePath [get, protected set] |
| The file path of the parameters. More... | |
Manage OpenCV's camera parameters from a calibration.
See the OpenCV documentation for more information about the calibration: http://docs.opencv.org/3.1.0/da/d13/tutorial_aruco_calibration.html
|
inline |
Create an empty CameraParameters and set CalibrationDateTime to now.
The constructor is needed for the serialization.
|
inline |
|
inlinestatic |
Create a new CameraParameters object from a previously saved camera parameters XML file.
| cameraParametersFilePath | The file path to load. |
| ArgumentException | If the camera parameters couldn't be loaded because of a wrong file path. |
|
inline |
Save the camera parameters to a XML file.
| cameraParametersFilePath | The file path where to save the object. |
| ArgumentException | If the camera parameters couldn't be saved because of a wrong file path. |
|
inlineprotected |
|
protected |
|
protected |
|
getset |
The calibration date and time.
|
getset |
The calibration flags used.
|
getset |
The camera matrix type of the calibration. Equals to CameraMatrix.Type() and automatically written when SaveToXmlFile(string) is called.
This property is be public for the serialization.
|
getprotected set |
The camera focal length expressed in pixels coordinates. Equals to CameraMatrix.AtDouble(0, 0) on the x-axis and to to CameraMatrix.AtDouble(1, 1) on the y-axis.
|
getset |
The camera matrix of the calibration.
When SaveToXmlFile(string) is called, it's serialized with the CameraMatrixType and CamerasMatrixValues properties.
|
getset |
The camera matrix values of the calibration. Equals to the CamerasMatrix content and automatically written when SaveToXmlFile(string) is called.
This property is be public for the serialization.
|
getprotected set |
|
getprotected set |
The camera optical center expressed in pixels coordinates. Equals to CameraMatrix.AtDouble(0, 2) on the x-axis and to CameraMatrix.AtDouble(1, 2) on the y-axis.
|
getset |
The distorsition coefficients of the calibration.
When SaveToXmlFile(string) is called, it's serialized with the DistCoeffsType and DistCoeffsValues properties.
|
getset |
The distorsition coefficients type of the calibration. Equals to DistCoeffs.Type() and automatically written when SaveToXmlFile(string) is called.
This property is be public for the serialization.
|
getset |
The distorsition coefficients values of the calibration. Equals to the DistCoeffs content and automatically written when SaveToXmlFile(string) is called.
This property is be public for the serialization.
|
getprotected set |
The file path of the parameters.
|
getset |
Non null if there is a fix image aspect ratio.
|
getset |
The image height during the calibration.
|
getset |
The image width during the calibration.
|
getprotected set |
The camera optical center in the Unity world space.
|
getset |
The average re-projection error of the calibration.


Home
Thank you for using Chef on the Go!
Please let us know about your experience Below
My Experience was ...
Absolutely Terrible
Sub-par
Good
Very Good
Amazing!
Enter your review here! Be sure to be descriptive, "It was good" tells fellow connoisseurs almost nothing about the chef.


| Figure 1 |
Selected meteorological stations and the climate Köppen of C ... |
| Figure 2 |
Distribution of average temperature in 60 years. |
| Figure 3 |
Temperature change and fluctuation in 60 years. |
| Figure 4 |
Seasonal temperature changes and fluctuations in 60 years. N ... |
| Figure 5 |
Distribution of average annual precipitation in 60 years. |
| Figure 6 |
Precipitation change and fluctuation in 60 years. |
| Figure 7 |
Seasonal precipitation changes and fluctuations in 60 years. ... |
| Figure 8 |
Cold spell duration indicator distribution and change. |
| Figure 9 |
Warm spell duration indicator distribution and change. |
| Figure 10 |
Cool nights indicator distribution and change. |
| Figure 11 |
Warm day indicator distribution and change. |
| Figure 12 |
Consecutive dry days indicator distribution and change. |
| Figure 13 |
Consecutive wet days indicator distribution and change. |
| Figure 14 |
Heavy precipitation days indicator distribution and change. |
| Figure 15 |
Very wet days indicator distribution and change. |


|
Dear Friend, You have been invited to join {{teamname}} on Givology.org, an online giving marketplace for education that allows you to contribute to grassroots education projects and student scholarships in the developing world. On Givology, your donation not only empowers students, but you can track your impact, read student updates and letters, and send messages in support! We believe in democratizing philanthropy and facilitating connections. To join the team, please click this link In order to join the team, you need to be registered on our site. Registering and contributing makes a huge difference in a child's life. Thank you! Sincerely, The Givology Team | ||


Class Style
Style implements features for changing visual appearance of controls by changing values of properties based on triggers and setters
Inheritance
System.Object
Style
Inherited Members
System.Object.Equals(System.Object)
System.Object.Equals(System.Object, System.Object)
System.Object.GetType()
System.Object.MemberwiseClone()
System.Object.ReferenceEquals(System.Object, System.Object)
System.Object.ToString()
Namespace: EmptyKeys.UserInterface
Assembly: EmptyKeys.UserInterface.dll
Syntax
public class Style
Constructors
Style()
Initializes a new instance of the Style class.
Declaration
public Style()
Style(Type)
Initializes a new instance of the Style class.
Declaration
public Style(Type targetType)
Parameters
| Type | Name | Description |
|---|---|---|
| System.Type | targetType | Type of the target. |
Style(Type, Style)
Initializes a new instance of the Style class.
Declaration
public Style(Type targetType, Style basedOn)
Parameters
| Type | Name | Description |
|---|---|---|
| System.Type | targetType | Type of the target. |
| Style | basedOn | The based on. |
Properties
BasedOn
Gets the based on.
Declaration
public Style BasedOn { get; }
Property Value
| Type | Description |
|---|---|
| Style | The based on. |
IsSealed
Gets a value indicating whether this instance is sealed.
Declaration
public bool IsSealed { get; }
Property Value
| Type | Description |
|---|---|
| System.Boolean |
|
Setters
Gets the setters.
Declaration
public List<Setter> Setters { get; }
Property Value
| Type | Description |
|---|---|
| System.Collections.Generic.List<Setter> | The setters. |
TargetType
Gets or sets the type of the target.
Declaration
public Type TargetType { get; set; }
Property Value
| Type | Description |
|---|---|
| System.Type | The type of the target. |
Triggers
Gets the triggers.
Declaration
public List<TriggerBase> Triggers { get; }
Property Value
| Type | Description |
|---|---|
| System.Collections.Generic.List<TriggerBase> | The triggers. |
Methods
GetHashCode()
Returns a hash code for this instance.
Declaration
public override int GetHashCode()
Returns
| Type | Description |
|---|---|
| System.Int32 | A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. |
Overrides
System.Object.GetHashCode()
Seal()
Seals this instance.
Declaration
public void Seal()


Focused and innovative Computer Science Professional with advanced knowledge of Object Oriented Design especially in regards to Java and Python. Looking to cooperate with coworkers in a small team environment and use both
my programming skills as well as experience in a team environment to contribute towards the success of a project.
Event Management Tool for Scrum Certifications as well as generic Meetups, Conferences, and Coaching. Used to connect those wanting certification with those that provide it. Made using Django, PostgreSQL, Bootstrap, JQuery, Nginx, and Gunicorn.
Basic Dodging Game Made Using the GoDot Engine. Implements random spawning, collision detection, and scoring. Compatible with Web, Android, and IOS.


Songs are constructed by playing a series of chords one at a time in sequence. Sequences of chords are called chord progressions, and many of the later parts of this book will explore how chords within a chord progression are chosen to make a pleasing sound. An example of a chord progression is shown below. Click play to hear how it sounds:
To reinforce the connection between the block representation and the scale degrees it represents, the next example shows the implied arrangement of scale degrees on the relative staff. Notice that in most of the chords, some of the scale degrees are played more than once.
The chord progression you just heard is starting to sound like music, but it really needs a melody to sound complete. In a previous section, we showed you the melody to “Livin’ On A Prayer” by Bon Jovi (it had scale degrees 1-1-1-7-6-5-3-4-4). The next example adds this melody to the chord progression you just heard. Click play to hear how it sounds:
This generic reproduction of “Livin’ On A Prayer” by Bon Jovi shows that the raw chords and melody capture much of what makes a song recognizable. Even though the example uses a generic arrangement for the chords, the chords and melody are immediately recognizable as “Livin’ On A Prayer” (assuming, of course, that you know the song). That’s because underneath all of the sparkle and shine, it’s the basic building blocks of a song that give it its overall character: its chords and melody.


XAMPP is a package containing several pieces of software. From wikipedia:
XAMPP is a free and open-source cross-platform web server solution stack package developed by Apache Friends, consisting mainly of the Apache HTTP Server, MariaDB database, and interpreters for scripts written in the PHP and Perl programming languages. Since most actual web server deployments use the same components as XAMPP, it makes transitioning from a local test server to a live server possible.
Letter Meaning
X as an ideographic letter referring to cross-platform
A Apache or its expanded form, Apache HTTP Server
M MariaDB (formerly: MySQL)
P PHP
P PERL
MySQL was replaced with MariaDB on 2015-10-19 and beginning with XAMPP versions 5.5.30 and 5.6.14, effectively altering the meaning of the acronym.
Wikipedia also has a table of xampp versions and what version of each software is included with it.
The best thing to do (if possible) is to install the version of XAMPP the target has to understand the versions and directory structure.


In randomized-controlled trials, interim analyses are often planned for possible early trial termination to claim superiority or futility of a new therapy. Blinded data also have information about the potential treatment difference between the groups. We developed a blinded data monitoring tool that enables investigators to predict whether they observe such an unblinded interim analysis results that supports early termination of the trial. Investigators may skip some of the planned interim analyses if an early termination is unlikely. This tool will provide reference information about N: Sample size at interim analysis, and T: Total number of responders at interim analysis for decision on performing an interim analysis.
| Version: | 1.0 |
| Imports: | graphics, stats |
| Suggests: | testthat, evaluate, knitr |
| Published: | 2017-08-11 |
| Author: | Kyongsun Pak |
| Maintainer: | Kyongsun Pak <pakk at pharm.kitasato-u.ac.jp> |
| License: | GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: | no |
| CRAN checks: | IAbin results |
| Reference manual: | IAbin.pdf |
| Vignettes: |
Vignette Title |
| Package source: | IAbin_1.0.tar.gz |
| Windows binaries: | r-devel: IAbin_1.0.zip, r-release: IAbin_1.0.zip, r-oldrel: IAbin_1.0.zip |
| OS X binaries: | r-release: IAbin_1.0.tgz, r-oldrel: IAbin_1.0.tgz |
Please use the canonical form https://CRAN.R-project.org/package=IAbin to link to this page.


Below is background decription of my educational status.
Software engineering
Bachelor of Science in Nursing
High School
Musa Gitau Primary School
I voluntered for a tech program in teaching young people about computer
packages and with time I grew interested in
computer languages.
I landed my first job at a small cyber cafe and did little of HTML and JAVASCRIPT.
My interest in taking programming is because I interacted
with the basics and grew curious
to know more about and with that i also learnt that there are other languages.


Fingerprintjs test
- Generate browser fingerprint.
- Save it to "localStorage" if first time visitor.
- Compare the generated hash with the stored one in localStorage in next visits.
- Notify user when the stored hash is not the same with the generated one (Hash has changed).
Your browser fingerprint:


One of the things that I’ve noticed since I’ve gotten here just under a year ago is the number of people with broken hearts or really rough stories. I don’t know if it’s just the writing aspect of this platform or the supportive community or some combination of factors, but I’ve seen a lot of heartbreak on here.
I’ve heard stories of financial loss, mental illness, depression, alcoholism, drug abuse, sexual abuse, illness, western medicine induced injury, homelessness, death of close friends and family, and suicidal tendencies. It’s tough to read a lot of this, but I’m also really stoked to see people trying to use this platform to heal. I’m equal parts sad to see so many people carrying such tragedy along with them, but I’m also really happy that they have a place to air out their soul injuries. I know I’ve been remarkably touched by the ourpouring of support for folks going through tough times on more than one occasion.
If you haven’t seen it yet there is a thing called spiritscience on the web and there are a bunch of parables that the author created. In the 2 minute video below they talk about how things are neither good nor bad because you don’t know what will happen as a result. I’ve been able to find some peace contemplating this and my own hardships.
https://www.youtube.com/watch?v=v4ozP5fHebc
This thing has had a profound impact on my thinking on things. Even things as difficult as the early death of my mother could fit into this.  The universe unfolds as it should even when it sucks. It’s along the same lines as everything happens for a reason, but it’s less about trying to determine the purpose of everything and more just floating as the universe flows past you rapids, eddies, and flow. We’re here to learn and experience not necessarily control.
Anyway, I’ve been thinking about this a lot as I keep meeting more and more people having a hard time. I’ll keep sending positive intention in the world for change and hope that my efforts expedite the transition to a world filled with peace, abundance, and liberty. If your soul is hurting know I’ll set my intention to spread reiki goodness to all who need it on steemit.
If you have a broken heart and a crushing story I hope you find solace and healing. If you’re bottling it up I think you’ll find a receptive audience here if you’re willing to talk about it positively and openly. Hang in there I guess. World seems to be in a transition state and hopefully before too long we’ll have a different path we walk together.
Namaste,
Aggroed
This page is synchronized from the post: ‘Steemit’’s broken heart club’


(function(window) {
(function(window) {
var sudo = {
delegates: {},
The sudo.extensions namespace holds the objects that are stand alone modules
which
can be implemented
(mixed-in) in sudo Class Objects
namespace
extensions: {},
Extract a value located at path
relative to the passed in object
param
{String} path
. The key in the form of a dot-delimited path.
param
{object} obj
. An object literal to operate on.
returns
{*|undefined}. The value at keypath or undefined if not found.
getPath: function getPath(path, obj) {
var key, p;
p = path.split('.');
for (key; p.length && (key = p.shift());) {
if(!p.length) {
return obj[key];
} else {
obj = obj[key] || {};
}
}
return obj;
},
Inherit the prototype from a parent to a child.
Set the childs constructor for subclasses of child.
Subclasses of the library base classes will not
want to use this function in most use-cases. Why? User Sudo Class Objects
possess their own constructors and any call back to a superclass
constructor
will generally be looking for the library Object's constructor.
param
{function} parent
param
{function} child
inherit: function inherit(parent, child) {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child;
},
Notice there is no need to extrinsically instruct how to make the sandwich, just the elegant single command.
returns
{string}
makeMeASandwich: function makeMeASandwich() {return 'Okay.';},
Method for assuring a Namespace is defined.
param
{string} path
. The path that leads to a blank Object.
namespace: function namespace(path) {
if (!this.getPath(path, window)) {
this.setPath(path, {}, window);
}
},
The premier object takes precedence over all others so define it at the topmost level.
type
{Object}
premier: null,
Traverse the keypath and get each object (or make blank ones) eventually setting the value at the end of the path
param
{string} path
. The path to traverse when setting a value.
param
{*} value
. What to set.
param
{Object} obj
. The object literal to operate on.
setPath: function setPath(path, value, obj) {
var p = path.split('.'), key;
for (key; p.length && (key = p.shift());) {
if(!p.length) {
obj[key] = value;
} else if (obj[key]) {
obj = obj[key];
} else {
obj = obj[key] = {};
}
}
},
Some sudo Objects use a unique integer as a tag
for identification.
(Views for example). This ensures they are indeed unique.
uid: 0,
An integer used as 'tags' by some sudo Objects as well as a unique string for views when needed
param
{string} prefix. Optional string identifier
unique: function unique(prefix) {
return prefix ? prefix + this.uid++ : this.uid++;
},
Remove a key:value pair from this object's data store
located at
param
{String} path
param
{Object} obj
The object to operate on.
unsetPath: function unsetPath(path, obj) {
var p = path.split('.'), key;
for (key; p.length && (key = p.shift());) {
if(!p.length) {
delete obj[key];
} else {
this can fail if a faulty path is passed. using getPath beforehand can prevent that
obj = obj[key];
}
}
}
};
All sudo.js objects inherit base, giving the ability
to utilize delegation, the base
function and the
construct
convenience method.
constructor
sudo.Base = function() {
can delegate
this.delegates = [];
a beautiful and unique snowflake
this.uid = sudo.unique();
};
Push an instance of a Class Object into this object's _delegates_
list.
param
{Object} an instance of a sudo.delegates Class Object
returns
{Object} this
sudo.Base.prototype.addDelegate = function addDelegate(del) {
del.delegator = this;
this.delegates.push(del);
if('addedAsDelegate' in del) del.addedAsDelegate(this);
return this;
};
Lookup the function matching the name passed in and call it with
any passed in argumets scoped to the calling object.
This method will avoid the recursive-loop problem by making sure
that the first match is not the function that called base
.
params
{*} any other number of arguments to be passed to the looked up method
along with the initial method name
sudo.Base.prototype.base = function base() {
var args = Array.prototype.slice.call(arguments),
name = args.shift(),
found = false,
obj = this,
curr;
find method on the prototype, excluding the caller
while(!found) {
curr = Object.getPrototypeOf(obj);
if(curr[name] && curr[name] !== this[name]) found = true;
keep digging
else obj = curr;
}
return curr[name].apply(this, args);
};
A convenience method that alleviates the need to place:
Object.getPrototypeOf(this).consturctor.apply(this, arguments)
in every constructor
sudo.Base.prototype.construct = function construct() {
Object.getPrototypeOf(this).constructor.apply(this, arguments || []);
};
From this object's list of delegates find the object whose _role_
matches
the passed name
and:
1. if meth
is falsy return the delegate.
2 if meth
is truthy bind its method (to the delegate) and return the method
param
{String} role
The role property to match in this object's delegates list
param
{String} meth
Optional method to bind to the action this delegate is being used for
returns
sudo.Base.prototype.delegate = function delegate(role, meth) {
var del = this.delegates, i;
for(i = 0; i < del.length; i++) {
if(del[i].role === role) {
if(!meth) return del[i];
return del[i][meth].bind(del[i]);
}
}
};
Fetch a delegate whose role property matches the passed in argument.
Uses the delegate
method in its 'single argument' form, included for
API consistency
param
{String} role
'returns' {Object|undefined}
sudo.Base.prototype.getDelegate = function getDelegate(role) {
return this.delegate(role);
};
From this objects delegates
list remove the object (there should only ever be 1)
whose role matches the passed in argument
param
{String} role
returns
{Object} this
sudo.Base.prototype.removeDelegate = function removeDelegate(role) {
var del = this.delegates, i;
for(i = 0; i < del.length; i++) {
if(del[i].role === role) {
no delegator for you
del[i].delegator = void 0;
del.splice(i, 1);
return this;
}
}
return this;
};
private
sudo.Base.prototype.role = 'base';
Model Objects expose methods for setting and getting data, and
can be observed if implementing the Observable Extension
param
{object} data. An initial state for this model.
constructor
sudo.Model = function(data) {
sudo.Base.call(this);
this.data = data || {};
only models are observable
this.callbacks = [];
this.changeRecords = [];
};
Model inherits from sudo.Base
private
sudo.inherit(sudo.Base, sudo.Model);
Returns the value associated with a key.
param
{String} key
. The name of the key
returns
{*}. The value associated with the key or false if not found.
sudo.Model.prototype.get = function get(key) {
return this.data[key];
};
Uses the sudo namespace's getpath function operating on the model's data hash.
returns
{*|undefined}. The value at keypath or undefined if not found.
sudo.Model.prototype.getPath = function getPath(path) {
return sudo.getPath(path, this.data);
};
Assembles and returns an object of key:value pairs for each key contained in the passed in Array.
param
{array} ary
. An array of keys.
returns
{object}
sudo.Model.prototype.gets = function gets(ary) {
var i, obj = {};
for (i = 0; i < ary.length; i++) {
obj[ary[i]] = ary[i].indexOf('.') === -1 ? this.data[ary[i]] :
this.getPath(ary[i]);
}
return obj;
};
private
sudo.Model.prototype.role = 'model';
Set a key:value pair.
param
{String} key
. The name of the key.
param
{*} value
. The value associated with the key.
returns
{Object} this
sudo.Model.prototype.set = function set(key, value) {
NOTE: intentional possibilty of setting a falsy value
this.data[key] = value;
return this;
};
Uses the sudo namespace's setpath function operating on the model's data hash.
param
{String} path
param
{*} value
returns
{Object} this.
sudo.Model.prototype.setPath = function setPath(path, value) {
sudo.setPath(path, value, this.data);
return this;
};
Invokes set()
or setPath()
for each key value pair in obj
.
Any listeners for those keys or paths will be called.
param
{Object} obj
. The keys and values to set.
returns
{Object} this
sudo.Model.prototype.sets = function sets(obj) {
var i, k = Object.keys(obj);
for(i = 0; i < k.length; i++) {
k[i].indexOf('.') === -1 ? this.set(k[i], obj[k[i]]) :
this.setPath(k[i], obj[k[i]]);
}
return this;
};
Remove a key:value pair from this object's data store
param
{String} key
returns
{Object} this
sudo.Model.prototype.unset = function unset(key) {
delete this.data[key];
return this;
};
Uses sudo.unsetPath
operating on this models data hash
param
{String} path
returns
{Object} this
sudo.Model.prototype.unsetPath = function unsetPath(path) {
sudo.unsetPath(path, this.data);
return this;
};
Deletes a number of keys or paths from this object's data store
param
{array} ary
. An array of keys or paths.
returns
{Objaect} this
sudo.Model.prototype.unsets = function unsets(ary) {
var i;
for(i = 0; i < ary.length; i++) {
ary[i].indexOf('.') === -1 ? this.unset(ary[i]) :
this.unsetPath(ary[i]);
}
return this;
};
A container is any object that can both contain other objects and itself be contained.
param
{Array|Object} 'arg'. Optional array or hash
of child objects which the Container will add as child objects
via addChildren
constructor
sudo.Container = function(arg) {
sudo.Base.call(this);
this.children = [];
this.childNames = {};
if(arg) this.addChildren(arg);
};
Container is a subclass of sudo.Base
sudo.inherit(sudo.Base, sudo.Container);
Adds a View to this container's list of children.
Also adds an 'index' property and an entry in the childNames hash.
If addedToParent
if found on the child, call it, sending this
as an argument.
param
{Object} child
. View (or View subclass) instance.
param
{String} name
. An optional name for the child that will go in the childNames hash.
returns
{Object} this
sudo.Container.prototype.addChild = function addChild(child, name) {
var c = this.children;
child.parent = this;
child.index = c.length;
if(name) {
child.name = name;
this.childNames[name] = child.index;
}
c.push(child);
if('addedToParent' in child) child.addedToParent(this);
return this;
};
Allows for multiple children to be added to this Container by passing either an Array or an Object literal.
see addChild
param
{Array|Object} arg
. An array of children to add or an
Object literal in the form {name: child}
returns
{Object} this
sudo.Container.prototype.addChildren = function addChildren(arg) {
var i, keys;
Array?
if(Array.isArray(arg)) {
for (i = 0; i < arg.length; i++) {
this.addChild(arg[i]);
}
} else {
keys = Object.keys(arg);
for (i = 0; i < keys.length; i++) {
this.addChild(arg[keys[i]] , keys[i]);
}
}
return this;
};
By default, bubble
returns the current view's parent (if it has one)
returns
{Object|undefined}
sudo.Container.prototype.bubble = function bubble() {return this.parent;};
If a child was added with a name, via addChild
,
that object can be fetched by name. This prevents us from having to reference a
containers children by index. That is possible however, though not preferred.
param
{String|Number} id
. The string name
or numeric index
of the child to fetch.
returns
{Object|undefined} The found child
sudo.Container.prototype.getChild = function getChild(id) {
return typeof id === 'string' ? this.children[this.childNames[id]] :
this.children[id];
};
Method is called with the index
property of a subview that is being removed.
Beginning at decrement subview indices.
param
{Number} i
private
sudo.Container.prototype._indexChildren_ = function _indexChildren_(i) {
var c = this.children, obj = this.childNames, len;
for (len = c.length; i < len; i++) {
c[i].index--;
adjust any entries in childNames
if(c[i].name in obj) obj[c[i].name] = c[i].index;
}
};
Find the intended child from my list of children and remove it, removing the name reference and re-indexing
remaining children. This method does not remove the child's DOM.
Override this method, doing whatever you want to the child's DOM, then call base('removeChild')
to do so.
param
{String|Number|Object} arg
. Children will always have an index
number, and optionally a name
.
If passed a string name
is assumed, so be sure to pass an actual number if expecting to use index.
An object will be assumed to be an actual sudo Class Object.
returns
{Object} this
sudo.Container.prototype.removeChild = function removeChild(arg) {
var i, t = typeof arg, c;
normalize the input
if(t === 'object') c = arg;
else c = t === 'string' ? this.children[this.childNames[arg]] : this.children[arg];
i = c.index;
remove from the children Array
this.children.splice(i, 1);
remove from the named child hash if present
delete this.childNames[c.name];
child is now an orphan
delete c.parent;
delete c.index;
delete c.name;
this._indexChildren_(i);
return this;
};
Remove all children, name references and adjust indexes accordingly. This method calls removeFromParent as each child may have overridden logic there.
see removeChild
returns
{object} this
sudo.Container.prototype.removeChildren = function removeChildren() {
while(this.children.length) {
this.children.shift().removeFromParent();
}
return this;
};
Remove this object from its parents list of children. Does not alter the dom - do that yourself by overriding this method or chaining method calls
sudo.Container.prototype.removeFromParent = function removeFromParent() {
will error without a parent, but that would be your fault...
this.parent.removeChild(this);
return this;
};
sudo.Container.prototype.role = 'container';
The call to the specific method on a (un)specified target happens here.
If this Object is part of a sudo.Container
maintained hierarchy
the 'target' may be left out, causing the bubble()
method to be called.
What this does is allow children of a sudo.Container
to simply pass
events upward, delegating the responsibility of deciding what to do to the parent.
TODO Currently, only the first target method found is called, then the bubbling is stopped. Should bubbling continue all the way up the 'chain'?
param
{*} Any number of arguments is supported, but the first is the only one searched for info.
A sendMethod will be located by:
1. using the first argument if it is a string
2. looking for a sendMethod
property if it is an object
In the case a specified target exists at this.model.get('sendTarget')
it will be used
Any other args will be passed to the sendMethod after this
returns
{Object} this
sudo.Container.prototype.send = function send(/*args*/) {
var args = Array.prototype.slice.call(arguments),
d = this.model && this.model.data, meth, targ, fn;
normalize the input, common use cases first
if(d && 'sendMethod' in d) meth = d.sendMethod;
else if(typeof args[0] === 'string') meth = args.shift();
less common but viable options
if(!meth) {
passed as a jquery custom data attr bound in events
meth = 'data' in args[0] ? args[0].data.sendMethod :
passed in a hash from something or not passed at all
args[0].sendMethod || void 0;
}
target is either specified or my parent
targ = d && d.sendTarget || this.bubble();
obvious chance for errors here, don't be dumb
fn = targ[meth];
while(!fn && (targ = targ.bubble())) {
fn = targ[meth];
}
sendMethods expect a signature (sender, ...)
if(fn) {
args.unshift(this);
fn.apply(targ, args);
}
return this;
};
Create an instance of a sudo.View object. A view is any object
that maintains its own el
, that being some type of DOM element.
Pass in a string selector or an actual dom node reference to have the object
set that as its el
. If no el
is specified one will be created upon instantiation
based on the tagName
(div
by default). Specify className
, id
(or other attributes if desired)
as an (optional) attributes
object literal on the data
arg.
The view object uses jquery for dom manipulation
and event delegation etc... A jquerified this
reference is located
at this.$el
and this.$
scopes queries to this objects el
, i.e it's
a shortcut for this.$el.find(selector)
param
{string|element|jQuery} el
. Otional el for the View instance.
param
{Object} data
. Optional data object-literal which becomes the initial state
of a new model located at this.model
. Also can be a reference to an existing sudo.Model instance
constructor
sudo.View = function(el, data) {
sudo.Container.call(this);
allow model instance to be passed in as well
if(data) {
this.model = data.role === 'model' ? data :
this.model = new sudo.Model(data);
}
this.setEl(el);
if(this.role === 'view') this.init();
};
View inherits from Container
private
sudo.inherit(sudo.Container, sudo.View);
Premier functionality provides hooks for behavioral differentiation among elements or class objects.
returns
{Object} this
sudo.View.prototype.becomePremier = function becomePremier() {
var p, f = function() {
this.isPremier = true;
sudo.premier = this;
}.bind(this);
is there an existing premier that isn't me?
if((p = sudo.premier) && p.uid !== this.uid) {
ask it to resign and call the cb
p.resignPremier(f);
} else f(); // no existing premier
return this;
};
A 'contruction-time' hook to call for further initialization needs in View objects (and their subclasses). A noop by default child classes should override.
sudo.View.prototype.init = $.noop;
the el needs to be normalized before use
private
sudo.View.prototype._normalizedEl_ = function _normalizedEl_(el) {
if(typeof el === 'string') {
return $(el);
} else {
Passed an already jquerified
Element?
It will have a length of 1 if so.
return el.length ? el : $(el);
}
};
Resign premier status
param
{Function} cb
. An optional callback to execute
after resigning premier status.
returns
{Object} this
sudo.View.prototype.resignPremier = function resignPremier(cb) {
var p;
this.isPremier = false;
only remove the global premier if it is me
if((p = sudo.premier) && p.uid === this.uid) {
sudo.premier = null;
}
fire the cb if passed
if(cb) cb();
return this;
};
private
sudo.View.prototype.role = 'view';
A view must have an element, set that here.
Stores a jquerified object as this.$el
the raw
node is always then available as this.$el[0]
.
param
{string=|element} el
returns
{Object} this
sudo.View.prototype.setEl = function setEl(el) {
var d = this.model && this.model.data, a, t;
if(!el) {
normalize any relevant data
t = d ? d.tagName || 'div': 'div';
this.$el = $(document.createElement(t));
if(d && (a = d.attributes)) this.$el.attr(a);
} else {
this.$el = this._normalizedEl_(el);
}
return this;
};
Return a single Element matching sel
scoped to this View's el.
This is an alias to this.$el.find(sel)
.
param
{string} sel
. A jQuery compatible selector
returns
{jQuery} A 'jquerified' result matching the selector
sudo.View.prototype.$ = function(sel) {
return this.$el.find(sel);
};
ViewControllers were designed for Rails projects for 2 specific use-cases:
ViewControllers can instantiate any descriptors
found in their model
when constructing, adding them as child
objects. Why? Sometimes a 'partial' will
need to define a javascript object that should, by design, be the child of a parent View
that is itself defined on the Rails view that owns the 'partial'. Since any JS introduced
by a partial will be parsed before the JS on its parent Rails View this usually isn't possible.
Our solution? Pushing Descriptor objects
(see docs) into an array (somewhere in your namespace) from a
'partial' and then passing a reference to that array into the ViewController as 'descriptors'
in its optional data argument when instantiated. The ViewController will then iterate over those
and instantiate them, adding them as children as it goes (also setting up any stated observers)
ViewControllers also abstract away connecting UJS style events by allowing the developer to
pass in the name(s) of any desired UJS events to observe: ujsEvent: ajax:success
for example,
and expect that a method named onAjaxSuccess, if present on the ViewController, will be called
with the arguments returned by the UJS plugin*
param
{string|element} el
. Otional el for the View instance.
param
{object} data
. Optional data object.
see
sudo.View.
constructor
sudo.ViewController = function(el, data) {
sudo.View.call(this, el, data);
map the names of events to methods we expect to proxy to
this.eventMap = {
'ajax:before': 'onAjaxBefore',
'ajax:beforeSend': 'onAjaxBeforeSend',
'ajax:success': 'onAjaxSuccess',
'ajax:error': 'onAjaxError',
'ajax:complete': 'onAjaxComplete',
'ajax:aborted:required': 'onAjaxAbortedRequired',
'ajax:aborted:file': 'onAjaxAbortedFile'
};
can be called again if mapping changes...
if(data) {
this.doMapping();
if('descriptor' in data) this.instantiateChildren([data.descriptor]);
else if('descriptors' in data) this.instantiateChildren();
}
if(this.role === 'viewController') this.init();
};
ViewController inherits from View.
private
sudo.inherit(sudo.View, sudo.ViewController);
assign the proxy mapping for events. This can be called at any time if the listened for events change
returns
{Object} this
sudo.ViewController.prototype.doMapping = function() {
either a single event or an array of them
var i,
toMap = this.model.data.ujsEvent || this.model.data.ujsEvents;
if(toMap) {
if(typeof toMap === 'string') this._mapEvent_(toMap);
else {
for(i = 0; i < toMap.length; i++) {
this._mapEvent_(toMap[i]);
}
}
}
return this;
};
sudo.ViewController.prototype._handleObserve_ = function _handleObserve_(obs, c) {
var obj = obs.object ? this._objectForPath_(obs.object) : this.model;
obj.observe(c[obs.cb].bind(c));
};
instantiate the children described in the passed in array or the descriptors
array
set in this object's data store
returns
{object} this
sudo.ViewController.prototype.instantiateChildren = function instantiateChildren(ary) {
var i, j, curr, c, d = ary || this.model.data.descriptors;
for(i = 0; i < d.length; i++) {
curr = d[i];
c = new curr.is_a(curr.el, curr.data);
this.addChild(c, curr.name);
handle any observe(s)
if('observe' in curr) {
this._handleObserve_(curr.observe, c);
}
else if('observes' in curr) {
for(j = 0; j < curr.observes.length; j++) {
this._handleObserve_(curr.observes[j], c);
}
}
}
return this;
};
sudo.ViewController.prototype._mapEvent_ = function _mapEvent_(name) {
because the signatures vary we need specific methods
this.$el.on(name, this[this.eventMap[name]].bind(this));
};
The objects used for callbacks and connections need to be
looked-up via a key-path like address as they likely will not exist
when viewController's are instantiated.
private
sudo.ViewController.prototype._objectForPath_ = function _objectForPath_(path) {
return sudo.getPath(path, window);
};
Virtual methods to override in your child classes for any events you chose to listen for
sudo.ViewController.prototype.onAjaxAbortedFile = $.noop;
sudo.ViewController.prototype.onAjaxAbortedRequired = $.noop;
sudo.ViewController.prototype.onAjaxBefore = $.noop;
sudo.ViewController.prototype.onAjaxBeforeSend = $.noop;
sudo.ViewController.prototype.onAjaxComplete = $.noop;
sudo.ViewController.prototype.onAjaxSuccess = $.noop;
sudo.ViewController.prototype.onAjaxError = $.noop;
private
sudo.ViewController.prototype.role = 'viewController';
Allow the default {{ js code }}, {{= key }}, and {{- escape stuff }} micro templating delimiters to be overridden if desired
type
{Object}
sudo.templateSettings = {
evaluate: /\{\{([\s\S]+?)\}\}/g,
interpolate: /\{\{=([\s\S]+?)\}\}/g,
escape: /\{\{-([\s\S]+?)\}\}/g
};
Certain characters need to be escaped so that they can be put into a string literal when templating.
type
{Object}
sudo.escapes = {};
(function(s) {
var e = {
'\\': '\\',
"'": "'",
r: '\r',
n: '\n',
t: '\t',
u2028: '\u2028',
u2029: '\u2029'
};
for (var key in e) s.escapes[e[key]] = key;
}(sudo));
sudo.htmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
};
sudo.escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
sudo.htmlEscaper = /[&<>"'\/]/g;
sudo.unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
sudo.escape = function(str) {
return str.replace(sudo.htmlEscaper, function(match) {
return sudo.htmlEscapes[match];
});
};
Within an interpolation, evaluation, or escaping, remove HTML escaping that had been previously added.
param
{string} str
sudo.unescape = function unescape(str) {
return str.replace(sudo.unescaper, function(match, escape) {
return sudo.escapes[escape];
});
};
JavaScript micro-templating, similar to John Resig's (and it's offspring) implementation.
sudo templating preserves whitespace, and correctly escapes quotes within interpolated code.
Unlike others sudo.template requires a scope name (to avoid the use of with
) and will spit at you
if it is not present.
param
{string} str
. The 'templated' string.
param
{Object} data
. Optional hash of key:value pairs.
param
{string} scope
. Optional context name of your data object
, set to 'data' if falsy.
sudo.template = function template(str, data, scope) {
scope || (scope = 'data');
var settings = sudo.templateSettings, render, template,
Compile the template source, taking care to escape characters that cannot be included in a string literal and then unescape them in code blocks.
source = "_p+='" + str.replace(sudo.escaper, function(match) {
return '\\' + sudo.escapes[match];
}).replace(settings.escape, function(match, code) {
return "'+\n((_t=(" + sudo.unescape(code) + "))==null?'':sudo.escape(_t))+\n'";
}).replace(settings.interpolate, function(match, code) {
return "'+\n((_t=(" + sudo.unescape(code) + "))==null?'':_t)+\n'";
}).replace(settings.evaluate, function(match, code) {
return "';\n" + sudo.unescape(code) + "\n_p+='";
}) + "';\n";
source = "var _t,_p='';" + source + "return _p;\n";
render = new Function(scope, source);
if (data) return render(data);
template = function(data) {
return render.call(this, data);
};
Provide the compiled function source as a convenience for reflection/compilation
template.source = 'function(' + scope + '){\n' + source + '}';
return template;
};
Create an instance of an Object, inheriting from sudo.View that:
1. Expects to have a template located in its internal data Store accessible via this.get('template')
.
2. Can have a renderTarget
property in its data store. If so this will be the location
the child injects itself into (if not already in) the DOM
3. Can have a 'renderMethod' property in its data store. If so this is the jQuery method
that the child will use to place itself in it's renderTarget
.
4. Has a render
method that when called re-hydrates it's $el by passing its
internal data store to its template
5. Handles event binding/unbinding by implementing the sudo.extensions.listener
extension object
constructor
sudo.DataView = function(el, data) {
sudo.View.call(this, el, data);
implements the listener extension
$.extend(this, sudo.extensions.listener);
dataview's models are observable, make it so if not already
if(!this.model.observe) $.extend(this.model, sudo.extensions.observable);
dont autoRender on the setting of events, add to this to prevent others if needed
this.autoRenderBlacklist = {event: true, events: true};
if autorendering, observe your own model use this ref to unobserve if desired
if(this.model.data.autoRender) this.observer = this.model.observe(this.render.bind(this));
this.build();
this.bindEvents();
if(this.role === 'dataview') this.init();
};
private
sudo.inherit(sudo.View, sudo.DataView);
Container's will check for the presence of this method and call it if it is present after adding a child - essentially, this will auto render the dataview when added to a parent
sudo.DataView.prototype.addedToParent = function(parent) {
return this.render();
};
Construct the innerHTML of the $el here so that the behavior of the
DataView, that the markup is ready after a subclass calls this.construct
,
is the same as other View classes -- IF there is a template available
there may not be yet as some get added later by a ViewController
sudo.DataView.prototype.build = function build() {
var t;
if(!(t = this.model.data.template)) return;
if(typeof t === 'string') t = sudo.template(t);
this.$el.html(t(this.model.data));
this.built = true;
return this;
};
Remove this object from the DOM and its parent's list of children.
Overrides sudo.View.removeFromParent
to actually remove the DOM as well
returns
{Object} this
sudo.DataView.prototype.removeFromParent = function removeFromParent() {
this.parent.removeChild(this);
this.$el.remove();
return this;
};
(Re)hydrate the innerHTML of this object via its template and internal data store.
If a renderTarget
is present this Object will inject itself into the target via
this.get('renderMethod')
or defualt to $.append
. After injection, the renderTarget
is deleted from this Objects data store.
Event unbinding/rebinding is generally not necessary for the Objects innerHTML as all events from the
Object's list of events (this.get('event(s)'))
are delegated to the $el on instantiation.
param
{object} change
dataviews may be observing their model if autoRender: true
returns
{Object} this
sudo.DataView.prototype.render = function render(change) {
var d;
return early if a blacklisted
key is set to my model
if(change && this.autoRenderBlacklist[change.name]) return this;
d = this.model.data;
has build
been executed already? If not call it again
if(!this.built) this.build();
if there is no template by this point you are doing it wrong erase the flag
else this.built = false;
if(d.renderTarget) {
this._normalizedEl_(d.renderTarget)[d.renderMethod || 'append'](this.$el);
delete d.renderTarget;
}
return this;
};
private
sudo.DataView.prototype.role = 'dataview';
Abstracts location and history events, parsing their information into a normalized object that is then set to an Observable class instance
constructor
sudo.Navigator = function(data) {
this.started = false;
this.slashStripper = /^\/+|\/+$/g;
this.leadingStripper = /^[#\/]|\s+$/g;
this.trailingStripper = /\/$/;
this.construct(data);
};
Navigator inherits from sudo.Model
sudo.Navigator.prototype = Object.create(sudo.Model.prototype);
'Fragment' is defined as any URL information after the 'root' path
including the search
or hash
returns
{String} fragment
returns
{String} the normalized current fragment
sudo.Navigator.prototype.getFragment = function getFragment(fragment) {
var root = this.data.root;
if(!fragment) {
intentional use of coersion
if (this.isPushState) {
fragment = window.location.pathname;
root = root.replace(this.trailingStripper, '');
if(!fragment.indexOf(root)) fragment = fragment.substr(root.length);
} else {
fragment = this.getHash();
}
}
return decodeURIComponent(fragment.replace(this.leadingStripper, ''));
};
Check either the passed in fragment, or the full location.href
for a hash
value
param
{string} fragment
Optional fragment to check
returns
{String} the normalized current hash
sudo.Navigator.prototype.getHash = function getHash(fragment) {
fragment || (fragment = window.location.href);
var match = fragment.match(/#(.*)$/);
return match ? match[1] : '';
};
Check either the passed in fragment, or the full location.href
for a search
value
param
{string} fragment
Optional fragment to check
returns
{String} the normalized current search
sudo.Navigator.prototype.getSearch = function getSearch(fragment) {
fragment || (fragment = window.location.href);
var match = fragment.match(/\?(.*)$/);
return match ? match[1] : '';
};
sudo.Navigator.prototype.getUrl = function getUrl() {
note that delegate(role) returns the deleagte
return this.data.root + this.data.fragment;
};
If the passed in 'fragment' is different than the currently stored one, push a new state entry / hash event and set the data where specified
param
{string} fragment
returns
{*} call to setData
sudo.Navigator.prototype.go = function go(fragment) {
if(!this.started) return false;
if(!this.urlChanged(fragment)) return;
TODO ever use replaceState?
if(this.isPushState) {
window.history.pushState({}, document.title, this.getUrl());
} else if(this.isHashChange) {
window.location.hash = '#' + this.data.fragment;
}
return this.setData();
};
Bound to either the popstate
or hashchange
events, if the
URL has indeed changed then parse the relevant data and set it -
triggering change observers
returns
{*} call to setData
or undefined
sudo.Navigator.prototype.handleChange = function handleChange(e) {
if(this.urlChanged()) {
return this.setData();
}
};
Parse and return a hash of the key value pairs contained in
the current query
returns
{object}
sudo.Navigator.prototype.parseQuery = function parseQuery() {
var obj = {}, seg = this.data.query,
i, s;
if(seg) {
seg = seg.split('&');
for(i = 0; i < seg.length; i++) {
if(!seg[i]) continue;
s = seg[i].split('=');
obj[s[0]] = s[1];
}
return obj;
}
};
Using the current fragment
(minus any search or hash data) as a key,
use parseQuery
as the value for the key, setting it into the specified
model (a stated Observable
or this.data
)
returns
{object} this
sudo.Navigator.prototype.setData = function setData() {
var frag = this.data.fragment,
data is set in a specified model or in self
observable = this.data.observable || this;
if(this.data.query) {
we want to set the key minus any search/hash
frag = frag.indexOf('?') !== -1 ? frag.split('?')[0] : frag.split('#')[0];
}
observable.set(frag, this.parseQuery());
return this;
};
Gather the necessary information about the current environment and bind to either (push|pop)state or hashchange. Also, if given an imcorrect URL for the current environment (hashchange vs pushState) normalize it and set accordingly (or don't).
returns
{object} this
sudo.Navigator.prototype.start = function start() {
var hasPushState, atRoot, loc, tmp;
if(this.started) return;
hasPushState = window.history && window.history.pushState;
this.started = true;
setup the initial configuration
this.isHashChange = this.data.useHashChange && 'onhashchange' in window ||
(!hasPushState && 'onhashchange' in window);
this.isPushState = !this.isHashChange && !!hasPushState;
normalize the root to always contain a leading and trailing slash
this.data['root'] = ('/' + this.data['root'] + '/').replace(this.slashStripper, '/');
Get a snapshot of the current fragment
this.urlChanged();
monitor URL changes via popState or hashchange
if (this.isPushState) {
$(window).on('popstate', this.handleChange.bind(this));
} else if (this.isHashChange) {
$(window).on('hashchange', this.handleChange.bind(this));
} else return;
atRoot = window.location.pathname.replace(/[^\/]$/, '$&/') === this.data['root'];
somehow a URL got here not in my 'format', unless explicitly told not too, correct this
if(!this.data.stay) {
if(this.isHashChange && !atRoot) {
window.location.replace(this.data['root'] + window.location.search + '#' +
this.data.fragment);
return early as browser will redirect
return true;
the converse of the above
} else if(this.isPushState && atRoot && window.location.hash) {
tmp = this.getHash().replace(this.leadingStripper, '');
window.history.replaceState({}, document.title, this.data['root'] +
tmp + window.location.search);
}
}
TODO provide option to go
from inital start
state?
return this;
};
Is a passed in fragment different from the one currently set at this.get('fragment')
?
If so set the fragment to the passed fragment passed in (as well as any 'query' data), else
simply return false
param
{String} fragment
returns
{bool}
sudo.Navigator.prototype.urlChanged = function urlChanged(fragment) {
var current = this.getFragment(fragment);
nothing has changed
if (current === this.data.fragment) return false;
this.data.fragment = current;
this.data.query = this.getSearch(current) || this.getHash(current);
return true;
};
Implementaion of the ES6 Harmony Observer pattern.
Extend a sudo.Model
class with this object if
data-mutation-observation is required
sudo.extensions.observable = {
_deliver_: function _deliver_(obj) {
var i, cb = this.callbacks;
for(i = 0; i < cb.length; i++) {
cb[i](obj);
}
},
Iterate through the changeRecords array(emptying it as you go), delivering them to the observers. You can override this method to change the standard delivery behavior.
returns
{Object} this
deliverChangeRecords: function deliverChangeRecords() {
var rec, cr = this.changeRecords;
FIFO
for(rec; cr.length && (rec = cr.shift());) {
this._deliver_(rec);
}
return this;
},
In a quasi-ES6 Object.observe pattern, calling observe on an observable
and
passing a callback will cause that callback to be called whenever any
property on the observable's data store is set, changed or deleted
via set, unset, setPath or unsetPath with an object containing:
{
type:
param
{Function} fn
The callback to be called with changeRecord(s)
returns
{Function} the Function passed in as an argument
observe: function observe(fn) {
this will fail if mixed-in and no callbacks
created so don't do that.
Per the spec, do not allow the same callback to be added
var d = this.callbacks;
if(d.indexOf(fn) === -1) d.push(fn);
return fn;
},
Allow an array of callbacks to be registered as changeRecord recipients
param
{Array} ary
returns
{Array} the Array passed in to observe
observes: function observes(ary) {
var i;
for(i = 0; i < ary.length; i++) {
this.observe(ary[i]);
}
return ary;
},
Overrides sudo.Base.set to check for observers
param
{String} key
. The name of the key
param
{*} value
param
{Bool} hold
Call deliver (falsy) or store the change notification
to be delivered upon a call to deliverChangeRecords (truthy)
returns
{Object|*} this
or calls deliverChangeRecords
set: function set(key, value, hold) {
var obj = {name: key, object: this.data};
did this key exist already
if(key in this.data) {
obj.type = 'updated';
then there is an oldValue
obj.oldValue = this.data[key];
} else obj.type = 'new';
now actually set the value
this.data[key] = value;
this.changeRecords.push(obj);
call the observers or not
if(hold) return this;
return this.deliverChangeRecords();
},
Overrides sudo.Base.setPath to check for observers.
Change records originating from a setPath
operation
send back the passed in path
as name
as well as the
top level object being observed (this observable's data).
this allows for easy filtering either manually or via a
change delegate
param
{String} path
param
{} value
param
{Bool} hold
Call deliver (falsy) or store the change notification
to be delivered upon a call to deliverChangeRecords (truthy)
returns
{Object|} this
or calls deliverChangeRecords
setPath: function setPath(path, value, hold) {
var curr = this.data, obj = {name: path, object: this.data},
p = path.split('.'), key;
for (key; p.length && (key = p.shift());) {
if(!p.length) {
reached the last refinement, pre-existing?
if (key in curr) {
obj.type = 'updated';
obj.oldValue = curr[key];
} else obj.type = 'new';
curr[key] = value;
} else if (curr[key]) {
curr = curr[key];
} else {
curr = curr[key] = {};
}
}
this.changeRecords.push(obj);
call all observers or not
if(hold) return this;
return this.deliverChangeRecords();
},
Overrides Base.sets to hold the call to deliver until all operations are done
returns
{Object|*} this
or calls deliverChangeRecords
sets: function sets(obj, hold) {
var i, k = Object.keys(obj);
for(i = 0; i < k.length; i++) {
k[i].indexOf('.') === -1 ? this.set(k[i], obj[k[i]], true) :
this.setPath(k[i], obj[k[i]], true);
}
if(hold) return this;
return this.deliverChangeRecords();
},
Remove a particular callback from this observable
param
{Function} the function passed in to observe
returns
{Object} this
unobserve: function unobserve(fn) {
var cb = this.callbacks, i = cb.indexOf(fn);
if(i !== -1) cb.splice(i, 1);
return this;
},
Allow an array of callbacks to be unregistered as changeRecord recipients
param
{Array} ary
returns
{Object} this
unobserves: function unobserves(ary) {
var i;
for(i = 0; i < ary.length; i++) {
this.unobserve(ary[i]);
}
return this;
},
Overrides sudo.Base.unset to check for observers
param
{String} key
. The name of the key
param
{Bool} hold
returns
{Object|*} this
or calls deliverChangeRecords
unset: function unset(key, hold) {
var obj = {name: key, object: this.data, type: 'deleted'},
val = !!this.data[key];
delete this.data[key];
call the observers if there was a val to delete
return this._unset_(obj, val, hold);
},
_unset_: function _unset_(o, v, h) {
if(v) {
this.changeRecords.push(o);
if(h) return this;
return this.deliverChangeRecords();
}
return this;
},
Overrides sudo.Base.unsetPath to check for observers
param
{String} path
param
{*} value
param
{bool} hold
returns
{Object|*} this
or calls deliverChangeRecords
unsetPath: function unsetPath(path, hold) {
var obj = {name: path, object: this.data, type: 'deleted'},
curr = this.data, p = path.split('.'),
key, val;
for (key; p.length && (key = p.shift());) {
if(!p.length) {
reached the last refinement
val = !!curr[key];
delete curr[key];
} else {
this can obviously fail, but can be prevented by checking
with getPath
first.
curr = curr[key];
}
}
return this._unset_(obj, val, hold);
},
Override of Base.unsets to hold the call to deliver until done
param
ary
param
hold
returns
{Object|*} this
or calls deliverChangeRecords
unsets: function unsets(ary, hold) {
var i;
for(i = 0; i < ary.length; i++) {
ary[i].indexOf('.') === -1 ? this.unset(k[i], true) :
this.unsetPath(k[i], true);
}
if(hold) return this;
return this.deliverChangeRecords();
}
};
Bindable methods allow various properties and attributes of a sudo Class Object to be synchronized with the data contained in a changeRecord recieved via observe().
namespace
sudo.extensions.bindable = {
_attr_: {
accesskey: true,
align: true,
alt: true,
contenteditable: true,
draggable: true,
href: true,
label: true,
name: true,
rel: true,
src: true,
tabindex: true,
title: true
},
_css_: {
display: true,
visibility: true
},
bind the jQuery prop() method to this object, now exposed
by this name, matching passed bindings
arguments.
param
{string} meth
The name of the method to be bound
returns
{Object} this
private
_handleAttr_: function _handleAttr_(meth) {
this[meth] = function(obj) {
if(obj.name === meth) this.$el.attr(meth, obj.object[obj.name]);
return this;
};
return this;
},
bind the jQuery css() method to this object, now exposed
by this name, matching passed bindings
arguments.
param
{string} meth
The name of the method to be bound
returns
{Object} this
private
_handleCss_: function _handleCss_(meth) {
this[meth] = function(obj) {
if(obj.name === meth) this.$el.css(meth, obj.object[obj.name]);
return this;
};
return this;
},
bind the jQuery data() method to this object, now exposed
by this name, matching passed bindings
arguments.
param
{string} meth
The name of the method to be bound
returns
{Object} this
private
_handleData_: function _handleData_(meth) {
this[meth] = function(obj) {
if(obj.name === meth) {
this.$el.data(obj.object[obj.name].key, obj.object[obj.name].value);
return this;
}
};
return this;
},
bind the jQuery attr() method to this object, now exposed
by this name, matching passed bindings
arguments.
NOTE: If more than 1 data-* attribute is desired you must
set those up manually as
param
{string} meth
The name of the method to be bound.
returns
{Object} this
private
_handleProp_: function _handleProp_(meth) {
this[meth] = function(obj) {
if(obj.name === meth) this.$el.prop(meth, obj.object[obj.name]);
return this;
};
return this;
},
bind the jQuery shorthand methods to this object matching
passed bindings
arguments.
param
{string} meth
The name of the method to be bound.
returns
{Object} this
private
_handleSpec_: function _handleSpec_(meth) {
this[meth] = function(obj) {
if(obj.name === meth) this.$el[meth](obj.object[obj.name]);
return this;
};
return this;
},
_prop_: {
checked: true,
defaultValue: true,
disabled: true,
location: true,
multiple: true,
readOnly: true,
selected: true
},
Given a single explicit binding, create it. Called from setbindings as a convenience for normalizing the single vs. multiple bindings scenario
param
{string} b
The binding.
private
_setBinding_: function _setBinding_(b) {
if(b in this._spec_) return this[this._spec_[b]](b);
if(b in this._css_) return this._handleCss_(b);
if(b in this._attr_) return this._handleAttr_(b);
if(b in this._prop_) return this._handleProp_(b);
},
Inspect the binding (in the single-bound use case), or the bindings Array in this Object's data store and create the bound functions expected.
returns
{Object} this
setBindings: function setBindings() {
var d = this.model.data, b, i;
handle the single binding use case
if((b = d.binding)) return this._setBinding_(b);
if(!(b = d.bindings)) return this;
for(i = 0; i < b.length; i++) {
this._setBinding_(b[i]);
}
return this;
},
_spec_: {
data: '_handleData_',
html: '_handleSpec_',
text: '_handleSpec_',
val: '_handleSpec_'
}
};
Handles event binding/unbinding via an events array in the form:
events: [{
name: eventName
,
sel: an_optional_delegator
,
data: an_optional_hash_of_data
fn: function name
}, {...
This array will be searched for via this.get('events')
. There is a
single-event use case as well, pass a single object literal in the above form.
with the key event
:
event: {...same as above}
Details about the hashes in the array:
A. name -> jQuery compatible event name
B. sel -> Optional jQuery compatible selector used to delegate events
C. data: A hash that will be passed as the custom jQuery Event.data object
D. fn -> If a {String} bound to the named function on this object, if a
function assumed to be anonymous and called with no scope manipulation
sudo.extensions.listener = {
bindEvents: function bindEvents() {
var e;
if((e = this.model.data.event || this.model.data.events)) this._handleEvents_(e, 1);
return this;
},
Use the jQuery on
or 'off' method, optionally delegating to a selector if present
private
_handleEvents_: function _handleEvents_(e, which) {
var i;
if(Array.isArray(e)) {
for(i = 0; i < e.length; i++) {
this._handleEvent_(e[i], which);
}
} else {
this._handleEvent_(e, which);
}
},
helper for binding and unbinding an individual event
param
{Object} e. An event descriptor
param
{String} which. on
or off
private
_handleEvent_: function _handleEvent_(e, which) {
if(which) {
this.$el.on(e.name, e.sel, e.data, typeof e.fn === 'string' ? this[e.fn].bind(this) : e.fn);
} else {
do not re-bind the fn going to off otherwise the unbind will fail
this.$el.off(e.name, e.sel);
}
},
rebindEvents: function rebindEvents() {
return this.unbindEvents().bindEvents();
},
unbindEvents: function unbindEvents() {
var e;
if((e = this.model.data.event || this.model.data.events)) this._handleEvents_(e);
return this;
}
};
A mixin providing restful CRUD operations for a sudo.Model instance.
create : POST read : GET update : PUT or PATCH (configurable) destroy : DELETE
Before use be sure to set an ajax
property {object} with at least
a baseUrl: ...
key. The model's id (if present -- indicating a persisted model)
is appended to the baseUrl (baseUrl/id) by default. You can override this behavior
by simply setting a url: ...
in the ajax
options hash or pass in the same when
calling any of the methods (or override the model.url() method).
Place any other default options in the ajax
hash
that you would want sent to a $.ajax({...}) call. Again, you can also override those
defaults by passing in a hash of options to any method:
this.model.update({patch: true})
etc...
sudo.extensions.persistable = {
Save this model on the server. If a subset of this model's attributes have not been stated (ajax:{data:{...}}) send all of the model's data. Anticipate that the server response will send back the state of the model on the server and set it here (via a success callback).
param
{object} params
Hash of options for the XHR call
returns
{object} The jQuery XHR object
create: function create(params) {
return this._sendData_('POST', params);
},
Delete this model on the server
param
{object} params
Optional hash of options for the XHR
returns
{object} jqXhr
destroy: function destroy(params) {
return this._sendData_('DELETE', params);
},
Abstracted logic for preparing the options object. This looks at
the set ajax
property, allowing any passed in params to override.
Sets defaults: JSON dataType and a success callback that simply sets()
the
data returned from the server
returns
{object} A normalized params object for the XHR call
_normalizeParams_: function _normalizeParams_(meth, opts, params) {
opts || (opts = $.extend({}, this.data.ajax));
opts.url || (opts.url = this.url(opts.baseUrl));
opts.type || (opts.type = meth);
opts.dataType || (opts.dataType = 'json');
the default success callback is to set the data returned from the server
or just the status as ajaxStatus
if no data was returned
opts.success || (opts.success = function(data, status, jqXhr) {
data ? this.sets(data) : this.set('ajaxStatus', status);
}.bind(this));
allow the passed in params to override any set in this model's ajax
options
return params ? $.extend(opts, params) : opts;
},
Fetch this models state from the server and set it here. The
Model.sets()
method is used with the returned data (we are
asssuming the default json dataType). Pass in (via the params arg)
a success function to override this default.
Maps to the http GET method.
param
{object} params
. Optional info for the XHR call. If
present will override any set in this model's ajax
options object.
returns
{object} The jQuery XHR object
read: function read(params) {
return $.ajax(this._normalizeParams_('GET', null, params));
},
Convenience method removing the need to know if a model is new (not yet persisted) or has been loaded/refreshed from the server.
param
{object} params
Hash of options for the XHR call
returns
{object} The jQuery XHR object
save: function save(params) {
return ('id' in this.data) ? this.update(params) : this.create(params);
},
The Create, Update and Patch methods all send data to the server, varying only in their HTTP method. Abstracted logic is here.
returns
{object} jqXhr
_sendData_: function _sendData_(meth, params) {
opts = $.extend({}, this.data.ajax);
opts.contentType || (opts.contentType = 'application/json');
opts.data || (opts.data = this.data);
non GET requests do not 'processData'
if(!('processData' in opts)) opts.processData = false;
return $.ajax(this._normalizeParams_(meth, opts, params));
},
If this model has been persisted to/from the server (it has an id
attribute)
send the specified data (or all the model's data) to the server at url
via
the PUT
http verb or PATCH
if {patch: true} is in the ajax options (or the
passed in params)
NOTE: update does not check is this is a new model or not, do that yourself
or use the save()
method (that does check).
param
{object} params
Optional hash of options for the XHR
returns
{object|bool} the jqXhr if called false if not
update: function update(params) {
return this._sendData_((this.data.ajax.patch || params && params.patch) ?
'PATCH' : 'PUT', params);
},
Takes the base url and appends this models id if present (narmalizing the trailong slash if needed). Override if you need to change the format of the calculated url.
param
{string} base
the baseUrl set in this models ajax options
url: function url(base) {
could possibly be 0...
if('id' in this.data) {
return base + (base.charAt(base.length - 1) === '/' ?
'' : '/') + encodeURIComponent(this.data.id);
} else return base;
}
};
Delegates, if present, can override or extend the behavior
of objects. The change delegate is specifically designed to
filter change records from an Observable instance and only forward
the ones matching a given filters
criteria (key or path).
The forwarded messages will be sent to the specified method
on the delegates delegator
(bound to the delegator scope)
param
{Object} data
sudo.delegates.Change = function(data) {
this.construct(data);
};
Delegates inherit from Model
sudo.delegates.Change.prototype = Object.create(sudo.Model.prototype);
Place an entry into this object's hash of filters
param
{string} key
param
{string} val
returns
{object} this
sudo.delegates.Change.prototype.addFilter = function addFilter(key, val) {
this.data.filters[key] = val;
return this;
};
Change records are delivered here and filtered, calling any matching methods specified in `this.get('filters').
returns
{Object} a call to the specified delegator method, passing
a hash containing:
1. the type
of Change
2. the name
of the changed property
3. the value located at the key/path
4. the oldValue
of the key if present
sudo.delegates.Change.prototype.filter = function filter(change) {
var filters = this.data.filters, name = change.name,
type = change.type, obj = {};
does my delegator care about this?
if(name in filters && filters.hasOwnProperty(name)) {
assemble the object to return to the method
obj.type = type;
obj.name = name;
obj.oldValue = change.oldValue;
delete operations will not have any value so no need to look
if(type !== 'deleted') {
obj.value = name.indexOf('.') === -1 ? change.object[change.name] :
sudo.getPath(name, change.object);
}
return this.delegator[filters[name]].call(this.delegator, obj);
}
};
Remove an entry from this object's hash of filters
param
{string} key
returns
{object} this
sudo.delegates.Change.prototype.removeFilter = function removeFilter(key) {
delete this.data.filters[key];
return this;
};
private
sudo.delegates.Change.prototype.role = 'change';
Delegates, if present, can extend the behavior of objects, lessening the need for subclassing. The data delegate is specifically designed to filter through an object, looking for specified keys or paths and returning values for those if found
param
{Object} data
returns
{*} the value found at the specified key/path if found
sudo.delegates.Data = function(data) {
this.construct(data);
};
inherits from Model
sudo.delegates.Data.prototype = Object.create(sudo.Model.prototype);
Place an entry into this object's hash of filters
param
{string} key
param
{string} val
returns
{object} this
sudo.delegates.Data.prototype.addFilter = function addFilter(key, val) {
this.data.filters[key] = val;
return this;
};
iterates over a given object literal and returns a value (if present) located at a given key or path
param
{Object} obj
sudo.delegates.Data.prototype.filter = function(obj) {
var filters = this.data.filters,
ary = Object.keys(filters), key, i, o, k;
for(i = 0; i < ary.length; i++) {
key = ary[i];
keys and paths need different handling
if(key.indexOf('.') === -1) {
if(key in obj) this.delegator[filters[key]].call(
this.delegator, obj[key]);
} else {
the chars after the last refinement are the key we need to check for
k = key.slice(key.lastIndexOf('.') + 1);
and the ones prior are the object
o = sudo.getPath(key.slice(0, key.lastIndexOf('.')), obj);
if(o && k in o) this.delegator[filters[key]].call(
this.delegator, o[k]);
}
}
};
Remove an entry from this object's hash of filters
param
{string} key
returns
{object} this
sudo.delegates.Data.prototype.removeFilter = function removeFilter(key) {
delete this.data.filters[key];
return this;
};
private
sudo.delegates.Data.prototype.role = 'data';
sudo.version = "0.9.5";
window.sudo = sudo;
if(typeof window._ === "undefined") window._ = sudo;
}).call(this, this);


This example is using YQL on the server to fetch data from the Github API.
It not only shows remote data fetching, but it shows how to use a partial view renderer to render different content on the same page.