Merge branch 'Chinese_tanslation' (#90)
Thanks @idalin user language should be detected from browser, or otherwise with enabled anonymous browsing it can be selected as admin (configure language for user guest). Annymous browsing can be deactivated afterwards
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
/*!
|
||||
* context.js Library associated with > v0.9.6.2 of intention.js
|
||||
* http://intentionjs.com/
|
||||
*
|
||||
* Copyright 2011, 2013 Dowjones and other contributors
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
var context = function($, Intention){
|
||||
|
||||
// create a brand spankin new intention object
|
||||
var intent=new Intention(),
|
||||
// placeholder for the horizontal axis
|
||||
horizontal_axis,
|
||||
orientation_axis;
|
||||
|
||||
// throttle funtion used for keeping calls to the resize responive
|
||||
// callback to a minimum
|
||||
function throttle(callback, interval){
|
||||
var lastExec = new Date(),
|
||||
timer = null;
|
||||
|
||||
return function(e){
|
||||
var d = new Date();
|
||||
if (d-lastExec < interval) {
|
||||
if (timer) {
|
||||
window.clearTimeout(timer);
|
||||
}
|
||||
var callbackWrapper = function(event){
|
||||
return function(){
|
||||
callback(event);
|
||||
};
|
||||
};
|
||||
timer = window.setTimeout(callbackWrapper(e), interval);
|
||||
return false;
|
||||
}
|
||||
callback(e);
|
||||
lastExec = d;
|
||||
};
|
||||
}
|
||||
|
||||
// catchall
|
||||
// =======================================================================
|
||||
intent.responsive([{name:'base'}]).respond('base');
|
||||
|
||||
// width context?
|
||||
// =======================================================================
|
||||
horizontal_axis = intent.responsive({
|
||||
ID:'width',
|
||||
contexts: [
|
||||
{name:'standard', min:840},
|
||||
{name:'tablet', min:510},
|
||||
{name:'mobile', min:0}],
|
||||
// compare the return value of the callback to each context
|
||||
// return true for a match
|
||||
matcher: function(test, context){
|
||||
if(typeof test === 'string'){
|
||||
|
||||
return test === context.name;
|
||||
}
|
||||
return test>=context.min;
|
||||
},
|
||||
// callback, return value is passed to matcher()
|
||||
// to compare against current context
|
||||
measure: function(arg){
|
||||
|
||||
if(typeof arg === 'string'){
|
||||
return arg;
|
||||
}
|
||||
|
||||
return $(window).width();
|
||||
}});
|
||||
|
||||
// orientation context?
|
||||
// =======================================================================
|
||||
orientation_axis = intent.responsive({
|
||||
ID:'orientation',
|
||||
contexts: [{name:'portrait', rotation: 0},
|
||||
{name:'landscape', rotation:90}],
|
||||
matcher: function(measure, ctx){
|
||||
return measure === ctx.rotation;
|
||||
},
|
||||
measure: function(){
|
||||
var test = Math.abs(window.orientation);
|
||||
if(test > 0) {
|
||||
test = 180 - test;
|
||||
}
|
||||
return test;
|
||||
}
|
||||
});
|
||||
|
||||
// ONE TIME CHECK AXES:
|
||||
// touch device?
|
||||
// =======================================================================
|
||||
intent.responsive({
|
||||
ID:'touch',
|
||||
contexts:[{name:'touch'}],
|
||||
matcher: function() {
|
||||
return "ontouchstart" in window;
|
||||
}}).respond();
|
||||
|
||||
// retina display?
|
||||
// =======================================================================
|
||||
intent.responsive({
|
||||
ID: 'highres',
|
||||
// contexts
|
||||
contexts:[{name:'highres'}],
|
||||
// matching:
|
||||
matcher: function(){
|
||||
return window.devicePixelRatio > 1;
|
||||
}}).respond();
|
||||
|
||||
// bind events to the window
|
||||
$(window).on('resize', throttle(horizontal_axis.respond, 100))
|
||||
.on('orientationchange', horizontal_axis.respond)
|
||||
.on('orientationchange', orientation_axis.respond);
|
||||
|
||||
// register the current width and orientation without waiting for a window
|
||||
// resize
|
||||
horizontal_axis.respond();
|
||||
orientation_axis.respond();
|
||||
|
||||
$(function(){
|
||||
// at doc ready grab all of the elements in the doc
|
||||
intent.elements(document);
|
||||
});
|
||||
|
||||
// return the intention object so that it can be extended by other plugins
|
||||
return intent;
|
||||
};
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define('context', ['jquery', 'intention'], factory);
|
||||
} else {
|
||||
// Browser globals
|
||||
root.intent = factory(root.jQuery, root.Intention);
|
||||
}
|
||||
}(this, function ($, Intention) {
|
||||
return context($, Intention);
|
||||
}));
|
||||
}).call(this);
|
||||
@@ -0,0 +1,564 @@
|
||||
/*!
|
||||
* intention.js Library v0.9.7.2
|
||||
* http://intentionjs.com/
|
||||
*
|
||||
* Copyright 2011, 2013 Dowjones and other contributors
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
|
||||
(function(root, factory) {
|
||||
|
||||
'use strict';
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define('intention', ['jquery', 'underscore'], factory);
|
||||
} else {
|
||||
root.Intention = factory(root.jQuery, root._);
|
||||
}
|
||||
}(this, function($, _) {
|
||||
'use strict';
|
||||
|
||||
var Intention = function(params){
|
||||
var intent = _.extend(this, params,
|
||||
{_listeners:{}, contexts:[], elms:$(), axes:{}, priority:[]});
|
||||
|
||||
return intent;
|
||||
};
|
||||
|
||||
Intention.prototype = {
|
||||
|
||||
// public methods
|
||||
responsive:function responsive(contexts, options){
|
||||
// for generating random ids for axis when not specified
|
||||
var idChars = 'abcdefghijklmnopqrstuvwxyz0123456789',
|
||||
id='', i;
|
||||
|
||||
// create a random id for the axis
|
||||
for(i=0; i<5; i++){
|
||||
id += idChars[Math.floor(Math.random() * idChars.length)];
|
||||
}
|
||||
var defaults = {
|
||||
// if no matcher function is specified expect to compare a
|
||||
// string to the ctx.name property
|
||||
matcher: function(measure, ctx){
|
||||
return measure === ctx.name;
|
||||
},
|
||||
// function takes one arg and returns it
|
||||
measure: _.identity,
|
||||
ID: id
|
||||
};
|
||||
|
||||
if(_.isObject(options) === false) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if((_.isArray(contexts)) && (_.isArray(contexts[0].contexts))){
|
||||
_.each(contexts, function(axis){
|
||||
responsive.apply(this, axis);
|
||||
}, this);
|
||||
return;
|
||||
}
|
||||
|
||||
if((_.isArray(contexts) === false) && _.isObject(contexts)){
|
||||
options = contexts;
|
||||
} else {
|
||||
options.contexts = contexts;
|
||||
}
|
||||
|
||||
// fill in the options
|
||||
options = _.extend({}, defaults, options);
|
||||
|
||||
// bind an the respond function to the axis ID and prefix it
|
||||
// with an underscore so that it does not get whomped accidentally
|
||||
this.on('_' + options.ID + ':', _.bind(
|
||||
function(e){
|
||||
this.axes = this._contextualize(
|
||||
options.ID, e.context, this.axes);
|
||||
this._respond(this.axes, this.elms);
|
||||
|
||||
}, this));
|
||||
|
||||
var axis = {
|
||||
ID:options.ID,
|
||||
current:null,
|
||||
contexts:options.contexts,
|
||||
respond:_.bind(this._responder(options.ID, options.contexts,
|
||||
options.matcher, options.measure), this)
|
||||
};
|
||||
|
||||
this.axes[options.ID] = axis;
|
||||
|
||||
this.axes.__keys__ = this.priority;
|
||||
|
||||
this.priority.unshift(options.ID);
|
||||
|
||||
return axis;
|
||||
},
|
||||
|
||||
elements: function(scope){
|
||||
|
||||
// find all responsive elms in a specific dom scope
|
||||
if(!scope){
|
||||
scope = document;
|
||||
}
|
||||
|
||||
$('[data-intent],[intent],[data-in],[in]',
|
||||
scope).each(_.bind(function(i, elm){
|
||||
this.add($(elm));
|
||||
}, this));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
add: function(elms, options){
|
||||
|
||||
var spec;
|
||||
|
||||
if(!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
// is expecting a jquery object
|
||||
elms.each(_.bind(function(i, elm){
|
||||
var exists = false;
|
||||
this.elms.each(function(i, respElm){
|
||||
if(elm === respElm) {
|
||||
exists=true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if(exists === false){
|
||||
// create the elements responsive data
|
||||
spec = this._fillSpec(
|
||||
_.extend(options, this._attrsToSpec(elm.attributes, this.axes)));
|
||||
// make any appropriate changes based on the current contexts
|
||||
this._makeChanges($(elm), spec, this.axes);
|
||||
|
||||
this.elms.push({
|
||||
elm: elm,
|
||||
spec: spec
|
||||
});
|
||||
}
|
||||
|
||||
}, this));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
remove: function(elms){
|
||||
// is expecting a jquery object
|
||||
var respElms = this.elms;
|
||||
// elms to remove
|
||||
elms.each(function(i, elm){
|
||||
// elms to check against
|
||||
respElms.each(function(i, candidate){
|
||||
if(elm === candidate.elm){
|
||||
respElms.splice(i, 1);
|
||||
// found the match, break the loop
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
is: function(ctxName){
|
||||
var axes = this.axes;
|
||||
return _.some(axes.__keys__, function(key){
|
||||
return ctxName === axes[key].current;
|
||||
});
|
||||
},
|
||||
|
||||
current: function(axisName){
|
||||
if(this.axes.hasOwnProperty(axisName)){
|
||||
return this.axes[axisName].current;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// code and concept taken from simple implementation of
|
||||
// observer pattern outlined here:
|
||||
// http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/
|
||||
on: function(type, listener){
|
||||
|
||||
var events = type.split(' '),
|
||||
i=0;
|
||||
|
||||
for(i;i<events.length;i++){
|
||||
if(this._listeners[events[i]] === undefined) {
|
||||
this._listeners[events[i]]=[];
|
||||
}
|
||||
this._listeners[events[i]].push(listener);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
off: function(type, listener){
|
||||
if(_.isArray(this._listeners[type])){
|
||||
var listeners = this._listeners[type],
|
||||
i;
|
||||
for(i=0;listeners.length; i++){
|
||||
if(listeners[i] === listener){
|
||||
listeners.splice(i,1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// privates
|
||||
_responder: function(axisID, contexts, matcher, measure){
|
||||
|
||||
var currentContext;
|
||||
|
||||
// called to perform a check
|
||||
return function(){
|
||||
|
||||
var measurement = measure.apply(this, arguments);
|
||||
|
||||
_.every(contexts, function(ctx){
|
||||
if( matcher(measurement, ctx)) {
|
||||
// first time, or different than last context
|
||||
if( (currentContext===undefined) ||
|
||||
(ctx.name !== currentContext.name)){
|
||||
|
||||
currentContext = ctx;
|
||||
|
||||
// event emitting!
|
||||
// emit the private axis event
|
||||
this._emitter(
|
||||
{_type: '_' + axisID + ':', context:currentContext.name},
|
||||
currentContext, this)
|
||||
|
||||
// emit the public axis event
|
||||
._emitter({_type: axisID + ':', context:currentContext.name},
|
||||
currentContext, this)
|
||||
|
||||
// attempt to trigger the axis to context pair
|
||||
._emitter(_.extend({},
|
||||
{_type: axisID + ':' + currentContext.name},
|
||||
currentContext), currentContext, this)
|
||||
|
||||
// then emit the context event (second ensures the context
|
||||
// changes happen after all dom manipulations)
|
||||
._emitter(_.extend({}, {_type:currentContext.name},
|
||||
currentContext), currentContext, this);
|
||||
|
||||
// done, break the loop
|
||||
return false;
|
||||
}
|
||||
// same context, break the loop
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, this);
|
||||
|
||||
// return the intention object for chaining
|
||||
return this;
|
||||
};
|
||||
},
|
||||
|
||||
_emitter: function(event){
|
||||
if(typeof event === 'string') {
|
||||
event={_type:event};
|
||||
}
|
||||
if(!event.target){
|
||||
event.target=this;
|
||||
}
|
||||
if(!event._type){
|
||||
throw new Error(event._type + ' is not a supported event.');
|
||||
}
|
||||
if(_.isArray(this._listeners[event._type])){
|
||||
var listeners = this._listeners[event._type],
|
||||
i;
|
||||
for(i=0; i<listeners.length; i++){
|
||||
listeners[i].apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_fillSpec: function(spec){
|
||||
|
||||
var applySpec = function(fn){
|
||||
_.each(spec, function(axisOptions, axis){
|
||||
_.each(axisOptions, function(ctxOptions, ctx){
|
||||
fn(ctxOptions, ctx, axis);
|
||||
});
|
||||
});
|
||||
}, filler={};
|
||||
|
||||
applySpec(function(options){
|
||||
// check to see if the ctx val is an object, could be a string
|
||||
if(_.isObject(options)){
|
||||
_.each(options, function(val, func){
|
||||
filler[func] = '';
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
applySpec(function(options, ctx, axis){
|
||||
if(_.isObject(options)){
|
||||
spec[axis][ctx] = _.extend({}, filler, options);
|
||||
}
|
||||
});
|
||||
|
||||
return spec;
|
||||
},
|
||||
|
||||
_assocAxis: function(ctx, axes){
|
||||
|
||||
var match=false;
|
||||
|
||||
_.every(axes.__keys__, function(axis){
|
||||
|
||||
if(match === false){
|
||||
_.every(axes[axis].contexts, function(ctxCandidate){
|
||||
if(ctxCandidate.name === ctx){
|
||||
match = axis;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return match;
|
||||
},
|
||||
|
||||
_makeSpec: function(axis, ctx, sAttr, value, spec){
|
||||
var axisObj,
|
||||
ctxObj;
|
||||
|
||||
if(spec[axis] !== undefined){
|
||||
axisObj = spec[axis];
|
||||
|
||||
if(axisObj[ctx] === undefined) {
|
||||
axisObj[ctx] = {};
|
||||
}
|
||||
} else {
|
||||
axisObj = {};
|
||||
axisObj[ctx] = {};
|
||||
spec[axis] = axisObj;
|
||||
}
|
||||
axisObj[ctx][sAttr] = value;
|
||||
|
||||
return spec;
|
||||
},
|
||||
|
||||
_attrsToSpec: function(attrs, axes){
|
||||
|
||||
var spec={},
|
||||
fullPattern = new RegExp(
|
||||
'^(data-)?(in|intent)-(([a-zA-Z0-9][a-zA-Z0-9]*:)?([a-zA-Z0-9]*))-([A-Za-z:-]+)'),
|
||||
axisPattern = new RegExp(
|
||||
'^(data-)?(in|intent)-([a-zA-Z0-9][_a-zA-Z0-9]*):$');
|
||||
|
||||
_.each(attrs, function(attr){
|
||||
|
||||
var specMatch = attr.name.match(fullPattern),
|
||||
axisName;
|
||||
|
||||
if(specMatch !== null) {
|
||||
|
||||
specMatch = specMatch.slice(-3);
|
||||
axisName = specMatch[0];
|
||||
|
||||
if(specMatch[0] === undefined){
|
||||
|
||||
// if there is no axis find one:
|
||||
specMatch[0] = this._assocAxis(specMatch[1], axes);
|
||||
|
||||
if(specMatch[0] === false) {
|
||||
// there is no context, so get outa here
|
||||
return; // skipt the attr
|
||||
}
|
||||
} else {
|
||||
specMatch[0] = specMatch[0].replace(/:$/, '');}
|
||||
|
||||
specMatch.push(attr.value);
|
||||
specMatch.push(spec);
|
||||
|
||||
spec = this._makeSpec.apply(this, specMatch);
|
||||
|
||||
} else if(axisPattern.test(attr.name)){
|
||||
|
||||
axisName = attr.name.match(axisPattern)[3];
|
||||
|
||||
_.each(axes[axisName].contexts,
|
||||
function(context){
|
||||
this._makeSpec(axisName, context.name, 'class', context.name +
|
||||
' ' + attr.value, spec);
|
||||
},
|
||||
this);}},
|
||||
this);
|
||||
|
||||
return spec;
|
||||
},
|
||||
|
||||
_contextSpec: function(ctxObj, specs){
|
||||
if(specs.hasOwnProperty(ctxObj.axis) &&
|
||||
specs[ctxObj.axis].hasOwnProperty(ctxObj.ctx)){
|
||||
return specs[ctxObj.axis][ctxObj.ctx];
|
||||
}
|
||||
return {};
|
||||
},
|
||||
_resolveSpecs: function(currentContexts, specs){
|
||||
|
||||
var changes={},
|
||||
moveFuncs=['append', 'prepend', 'before', 'after'];
|
||||
|
||||
_.each(currentContexts, function(ctxObj){
|
||||
// if the axis or the context to not exist in the specs object
|
||||
// skip to the next one
|
||||
_.each(this._contextSpec(ctxObj, specs), function(val, func){
|
||||
|
||||
if(func==='class'){
|
||||
if(!changes[func]){
|
||||
changes[func] = [];
|
||||
}
|
||||
changes[func] = _.union(changes[func], val.split(' '));
|
||||
|
||||
} else if(((changes.move === undefined) ||
|
||||
(changes.move.value === '')) &&
|
||||
($.inArray(func, moveFuncs) !== -1)){
|
||||
|
||||
changes.move = {value:val, placement:func};
|
||||
|
||||
} else {
|
||||
if((changes[func] === undefined) || (changes[func] === '')){
|
||||
changes[func]=val;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
return changes;
|
||||
},
|
||||
|
||||
_currentContexts: function(axes) {
|
||||
var contexts = [];
|
||||
|
||||
_.each(axes.__keys__, function(ID){
|
||||
if(axes[ID].current !== null) {
|
||||
contexts.push({ctx:axes[ID].current, axis:ID});
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return contexts;
|
||||
},
|
||||
|
||||
_removeClasses: function(specs, axes) {
|
||||
|
||||
var toRemove = [];
|
||||
|
||||
_.each(axes.__keys__, function(key){
|
||||
|
||||
var axis = axes[key];
|
||||
|
||||
_.each(axis.contexts, function(ctx){
|
||||
|
||||
// ignore the current context, those classes SHOULD be applied
|
||||
if(ctx.name === axis.current) {
|
||||
return;
|
||||
}
|
||||
var contextSpec = this._contextSpec(
|
||||
{axis:axis.ID, ctx:ctx.name}, specs),
|
||||
classes;
|
||||
|
||||
if(contextSpec !== undefined) {
|
||||
if(contextSpec['class'] !== undefined) {
|
||||
classes = contextSpec['class'].split(' ');
|
||||
if(classes !== undefined){
|
||||
toRemove = _.union(toRemove, classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
}, this);
|
||||
|
||||
return toRemove;
|
||||
},
|
||||
|
||||
_contextConfig: function(specs, axes){
|
||||
|
||||
return this._resolveSpecs(this._currentContexts(axes), specs, axes);
|
||||
},
|
||||
|
||||
_makeChanges: function(elm, specs, axes){
|
||||
|
||||
if(_.isEmpty(axes)===false){
|
||||
var ctxConfig = this._contextConfig(specs, axes);
|
||||
|
||||
_.each(ctxConfig, function(change, func){
|
||||
if(func==='move'){
|
||||
if( (specs.__placement__ !== change.placement) ||
|
||||
(specs.__move__ !== change.value)){
|
||||
|
||||
$(change.value)[change.placement](elm);
|
||||
|
||||
// save the last placement of the element so
|
||||
// we're not moving it around for no good reason
|
||||
specs.__placement__ = change.placement;
|
||||
specs.__move__ = change.value;
|
||||
}
|
||||
} else if(func === 'class') {
|
||||
|
||||
var classes = elm.attr('class') || '';
|
||||
|
||||
// the class add/remove formula
|
||||
classes = _.union(change,
|
||||
_.difference(classes.split(' '),
|
||||
this._removeClasses(specs, axes)));
|
||||
|
||||
elm.attr('class', classes.join(' '));
|
||||
|
||||
} else {
|
||||
elm.attr(func, change);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
return elm;
|
||||
},
|
||||
|
||||
_respond: function(axes, elms){
|
||||
// go through all of the responsive elms
|
||||
elms.each(_.bind(function(i, elm){
|
||||
var $elm = $(elm.elm);
|
||||
this._makeChanges($elm, elm.spec, axes);
|
||||
$elm.trigger('intent', this);
|
||||
}, this));
|
||||
},
|
||||
|
||||
_contextualize: function(axisID, context, axes){
|
||||
axes[axisID].current = context;
|
||||
return axes;
|
||||
},
|
||||
|
||||
// private props
|
||||
|
||||
// axis test, does it begin with an underscore? for testing inside
|
||||
// spec objects
|
||||
_axis_test_pattern: new RegExp("^_[a-zA-Z0-9]"),
|
||||
|
||||
// match a group after the underscore:
|
||||
_axis_match_pattern: new RegExp("^_([a-zA-Z0-9][_a-zA-Z0-9]*)"),
|
||||
|
||||
// simple trim
|
||||
_trim_pattern:new RegExp( "^\s+|\s+$", "g" )
|
||||
};
|
||||
|
||||
return Intention;
|
||||
}));
|
||||
Reference in New Issue
Block a user