aboutsummaryrefslogtreecommitdiffstats
path: root/core/js
diff options
context:
space:
mode:
authorThomas Müller <thomas.mueller@tmit.eu>2014-04-02 08:48:37 +0200
committerThomas Müller <thomas.mueller@tmit.eu>2014-04-02 08:48:37 +0200
commit7086c386fdd1cfcec0ddc0db19615bd4586bade3 (patch)
tree26d7a890bc0350af5260bb7a3736610e533e6d3b /core/js
parent229e3dcba86db3bd91bbddd78079bf340edff710 (diff)
parent73dd5ff26c2d7652fd4abacbac53d734f64fde96 (diff)
downloadnextcloud-server-7086c386fdd1cfcec0ddc0db19615bd4586bade3.tar.gz
nextcloud-server-7086c386fdd1cfcec0ddc0db19615bd4586bade3.zip
Merge branch 'master' into append-error-document
Conflicts: lib/private/setup.php lib/private/updater.php
Diffstat (limited to 'core/js')
-rw-r--r--core/js/core.json1
-rw-r--r--core/js/jquery.avatar.js41
-rw-r--r--core/js/js.js151
-rw-r--r--core/js/router.js81
-rw-r--r--core/js/setup.js2
-rw-r--r--core/js/share.js32
-rw-r--r--core/js/tags.js18
-rw-r--r--core/js/tests/specHelper.js16
-rw-r--r--core/js/tests/specs/coreSpec.js127
9 files changed, 320 insertions, 149 deletions
diff --git a/core/js/core.json b/core/js/core.json
index 4beab7cf796..665e2485a90 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -17,7 +17,6 @@
"eventsource.js",
"config.js",
"multiselect.js",
- "router.js",
"oc-requesttoken.js"
]
}
diff --git a/core/js/jquery.avatar.js b/core/js/jquery.avatar.js
index 02a40c088b4..381c42d9dbb 100644
--- a/core/js/jquery.avatar.js
+++ b/core/js/jquery.avatar.js
@@ -75,31 +75,32 @@
var $div = this;
- OC.Router.registerLoadedCallback(function() {
- var url = OC.Router.generate('core_avatar_get', {user: user, size: size})+'?requesttoken='+oc_requesttoken;
- $.get(url, function(result) {
- if (typeof(result) === 'object') {
- if (!hidedefault) {
- if (result.data && result.data.displayname) {
- $div.imageplaceholder(user, result.data.displayname);
- } else {
- $div.imageplaceholder(user);
- }
+ var url = OC.generateUrl(
+ '/avatar/{user}/{size}?requesttoken={requesttoken}',
+ {user: user, size: size, requesttoken: oc_requesttoken});
+
+ $.get(url, function(result) {
+ if (typeof(result) === 'object') {
+ if (!hidedefault) {
+ if (result.data && result.data.displayname) {
+ $div.imageplaceholder(user, result.data.displayname);
} else {
- $div.hide();
+ $div.imageplaceholder(user);
}
} else {
- $div.show();
- if (ie8fix === true) {
- $div.html('<img src="'+url+'#'+Math.floor(Math.random()*1000)+'">');
- } else {
- $div.html('<img src="'+url+'">');
- }
+ $div.hide();
}
- if(typeof callback === 'function') {
- callback();
+ } else {
+ $div.show();
+ if (ie8fix === true) {
+ $div.html('<img src="'+url+'#'+Math.floor(Math.random()*1000)+'">');
+ } else {
+ $div.html('<img src="'+url+'">');
}
- });
+ }
+ if(typeof callback === 'function') {
+ callback();
+ }
});
};
}(jQuery));
diff --git a/core/js/js.js b/core/js/js.js
index 21ccee0f1d5..302b6b4d9fa 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -27,7 +27,7 @@ if (oc_debug !== true || typeof console === "undefined" || typeof console.log ==
if (!window.console) {
window.console = {};
}
- var methods = ['log', 'debug', 'warn', 'info', 'error', 'assert'];
+ var methods = ['log', 'debug', 'warn', 'info', 'error', 'assert', 'time', 'timeEnd'];
for (var i = 0; i < methods.length; i++) {
console[methods[i]] = function () { };
}
@@ -194,6 +194,30 @@ var OC={
linkToRemoteBase:function(service) {
return OC.webroot + '/remote.php/' + service;
},
+
+ /**
+ * Generates the absolute url for the given relative url, which can contain parameters.
+ *
+ * @returns {string}
+ * @param {string} url
+ * @param params
+ */
+ generateUrl: function(url, params) {
+ var _build = function (text, vars) {
+ return text.replace(/{([^{}]*)}/g,
+ function (a, b) {
+ var r = vars[b];
+ return typeof r === 'string' || typeof r === 'number' ? r : a;
+ }
+ );
+ };
+ if (url.charAt(0) !== '/') {
+ url = '/' + url;
+
+ }
+ return OC.webroot + '/index.php' + _build(url, params);
+ },
+
/**
* @brief Creates an absolute url for remote use
* @param string $service id
@@ -458,6 +482,53 @@ var OC={
}).show();
}, 'html');
}
+ },
+
+ // for menu toggling
+ registerMenu: function($toggle, $menuEl) {
+ $menuEl.addClass('menu');
+ $toggle.addClass('menutoggle');
+ $toggle.on('click.menu', function(event) {
+ if ($menuEl.is(OC._currentMenu)) {
+ $menuEl.hide();
+ OC._currentMenu = null;
+ OC._currentMenuToggle = null;
+ return false;
+ }
+ // another menu was open?
+ else if (OC._currentMenu) {
+ // close it
+ OC._currentMenu.hide();
+ }
+ $menuEl.show();
+ OC._currentMenu = $menuEl;
+ OC._currentMenuToggle = $toggle;
+ return false
+ });
+ },
+
+ unregisterMenu: function($toggle, $menuEl) {
+ // close menu if opened
+ if ($menuEl.is(OC._currentMenu)) {
+ $menuEl.hide();
+ OC._currentMenu = null;
+ OC._currentMenuToggle = null;
+ }
+ $toggle.off('click.menu').removeClass('menutoggle');
+ $menuEl.removeClass('menu');
+ },
+
+ /**
+ * Wrapper for matchMedia
+ *
+ * This is makes it possible for unit tests to
+ * stub matchMedia (which doesn't work in PhantomJS)
+ */
+ _matchMedia: function(media) {
+ if (window.matchMedia) {
+ return window.matchMedia(media);
+ }
+ return false;
}
};
OC.search.customResults={};
@@ -638,6 +709,9 @@ if(typeof localStorage !=='undefined' && localStorage !== null){
setItem:function(name,item){
return localStorage.setItem(OC.localStorage.namespace+name,JSON.stringify(item));
},
+ removeItem:function(name,item){
+ return localStorage.removeItem(OC.localStorage.namespace+name);
+ },
getItem:function(name){
var item = localStorage.getItem(OC.localStorage.namespace+name);
if(item===null) {
@@ -685,11 +759,11 @@ SVGSupport.checkMimeType=function(){
if(value[0]==='"'){
value=value.substr(1,value.length-2);
}
- headers[parts[0]]=value;
+ headers[parts[0].toLowerCase()]=value;
}
}
});
- if(headers["Content-Type"]!=='image/svg+xml'){
+ if(headers["content-type"]!=='image/svg+xml'){
replaceSVG();
SVGSupport.checkMimeType.correct=false;
}
@@ -791,12 +865,10 @@ function initCore() {
if (interval < 60) {
interval = 60;
}
- OC.Router.registerLoadedCallback(function(){
- var url = OC.Router.generate('heartbeat');
- setInterval(function(){
- $.post(url);
- }, interval * 1000);
- });
+ var url = OC.generateUrl('/heartbeat');
+ setInterval(function(){
+ $.post(url);
+ }, interval * 1000);
}
// session heartbeat (defaults to enabled)
@@ -915,6 +987,67 @@ function initCore() {
$('a.action').tipsy({gravity:'s', fade:true, live:true});
$('td .modified').tipsy({gravity:'s', fade:true, live:true});
$('input').tipsy({gravity:'w', fade:true});
+
+ // toggle for menus
+ $(document).on('mouseup.closemenus', function(event) {
+ var $el = $(event.target);
+ if ($el.closest('.menu').length || $el.closest('.menutoggle').length) {
+ // don't close when clicking on the menu directly or a menu toggle
+ return false;
+ }
+ if (OC._currentMenu) {
+ OC._currentMenu.hide();
+ }
+ OC._currentMenu = null;
+ OC._currentMenuToggle = null;
+ });
+
+
+ /**
+ * Set up the main menu toggle to react to media query changes.
+ * If the screen is small enough, the main menu becomes a toggle.
+ * If the screen is bigger, the main menu is not a toggle any more.
+ */
+ function setupMainMenu() {
+ // toggle the navigation on mobile
+ if (!OC._matchMedia) {
+ return;
+ }
+ var mq = OC._matchMedia('(max-width: 768px)');
+ var lastMatch = mq.matches;
+ var $toggle = $('#header #owncloud');
+ var $navigation = $('#navigation');
+
+ function updateMainMenu() {
+ // mobile mode ?
+ if (lastMatch && !$toggle.hasClass('menutoggle')) {
+ // init the menu
+ OC.registerMenu($toggle, $navigation);
+ $toggle.data('oldhref', $toggle.attr('href'));
+ $toggle.attr('href', '#');
+ $navigation.hide();
+ }
+ else {
+ OC.unregisterMenu($toggle, $navigation);
+ $toggle.attr('href', $toggle.data('oldhref'));
+ $navigation.show();
+ }
+ }
+
+ updateMainMenu();
+
+ // TODO: debounce this
+ $(window).resize(function() {
+ if (lastMatch !== mq.matches) {
+ lastMatch = mq.matches;
+ updateMainMenu();
+ }
+ });
+ }
+
+ if (window.matchMedia) {
+ setupMainMenu();
+ }
}
$(document).ready(initCore);
diff --git a/core/js/router.js b/core/js/router.js
deleted file mode 100644
index e6ef54a1864..00000000000
--- a/core/js/router.js
+++ /dev/null
@@ -1,81 +0,0 @@
-OC.router_base_url = OC.webroot + '/index.php';
-OC.Router = {
- // register your ajax requests to load after the loading of the routes
- // has finished. otherwise you face problems with race conditions
- registerLoadedCallback: function(callback){
- if (!this.routes_request){
- return;
- }
- this.routes_request.done(callback);
- },
- routes_request: !window.TESTING && $.ajax(OC.router_base_url + '/core/routes.json', {
- dataType: 'json',
- success: function(jsondata) {
- if (jsondata.status === 'success') {
- OC.Router.routes = jsondata.data;
- }
- }
- }),
- generate:function(name, opt_params) {
- if (!('routes' in this)) {
- if(this.routes_request.state() != 'resolved') {
- console.warn('To avoid race conditions, please register a callback');// wait
- }
- }
- if (!(name in this.routes)) {
- throw new Error('The route "' + name + '" does not exist.');
- }
- var route = this.routes[name];
- var params = opt_params || {};
- var unusedParams = $.extend(true, {}, params);
- var url = '';
- var optional = true;
- $(route.tokens).each(function(i, token) {
- if ('text' === token[0]) {
- url = token[1] + url;
- optional = false;
-
- return;
- }
-
- if ('variable' === token[0]) {
- if (false === optional || !(token[3] in route.defaults)
- || ((token[3] in params) && params[token[3]] != route.defaults[token[3]])) {
- var value;
- if (token[3] in params) {
- value = params[token[3]];
- delete unusedParams[token[3]];
- } else if (token[3] in route.defaults) {
- value = route.defaults[token[3]];
- } else if (optional) {
- return;
- } else {
- throw new Error('The route "' + name + '" requires the parameter "' + token[3] + '".');
- }
-
- var empty = true === value || false === value || '' === value;
-
- if (!empty || !optional) {
- url = token[1] + encodeURIComponent(value).replace(/%2F/g, '/') + url;
- }
-
- optional = false;
- }
-
- return;
- }
-
- throw new Error('The token type "' + token[0] + '" is not supported.');
- });
- if (url === '') {
- url = '/';
- }
-
- unusedParams = $.param(unusedParams);
- if (unusedParams.length > 0) {
- url += '?'+unusedParams;
- }
-
- return OC.router_base_url + url;
- }
-}
diff --git a/core/js/setup.js b/core/js/setup.js
index 279b5fbebb9..96719540f96 100644
--- a/core/js/setup.js
+++ b/core/js/setup.js
@@ -36,6 +36,7 @@ $(document).ready(function() {
$('#showAdvanced').click(function() {
$('#datadirContent').slideToggle(250);
+ $('#databaseBackend').slideToggle(250);
$('#databaseField').slideToggle(250);
});
$("form").submit(function(){
@@ -73,6 +74,7 @@ $(document).ready(function() {
if (currentDbType === 'sqlite' || (dbtypes.sqlite && currentDbType === undefined)){
$('#datadirContent').hide(250);
+ $('#databaseBackend').hide(250);
$('#databaseField').hide(250);
}
diff --git a/core/js/share.js b/core/js/share.js
index 0939259b7da..ef71cc7999a 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -48,7 +48,7 @@ OC.Share={
var action = $(file).find('.fileactions .action[data-action="Share"]');
var img = action.find('img').attr('src', image);
action.addClass('permanent');
- action.html(' '+t('core', 'Shared')).prepend(img);
+ action.html(' <span>'+t('core', 'Shared')+'</span>').prepend(img);
} else {
var dir = $('#dir').val();
if (dir.length > 1) {
@@ -63,7 +63,7 @@ OC.Share={
if (img.attr('src') != OC.imagePath('core', 'actions/public')) {
img.attr('src', image);
$(action).addClass('permanent');
- $(action).html(' '+t('core', 'Shared')).prepend(img);
+ $(action).html(' <span>'+t('core', 'Shared')+'</span>').prepend(img);
}
});
}
@@ -103,10 +103,10 @@ OC.Share={
var img = action.find('img').attr('src', image);
if (shares) {
action.addClass('permanent');
- action.html(' '+ escapeHTML(t('core', 'Shared'))).prepend(img);
+ action.html(' <span>'+ escapeHTML(t('core', 'Shared'))+'</span>').prepend(img);
} else {
action.removeClass('permanent');
- action.html(' '+ escapeHTML(t('core', 'Share'))).prepend(img);
+ action.html(' <span>'+ escapeHTML(t('core', 'Share'))+'</span>').prepend(img);
}
}
}
@@ -551,7 +551,7 @@ $(document).ready(function() {
var itemType = $('#dropdown').data('item-type');
var itemSource = $('#dropdown').data('item-source');
var shareType = $li.data('share-type');
- var shareWith = $li.data('share-with');
+ var shareWith = $li.attr('data-share-with');
OC.Share.unshare(itemType, itemSource, shareType, shareWith, function() {
$li.remove();
var index = OC.Share.itemShares[shareType].indexOf(shareWith);
@@ -584,8 +584,8 @@ $(document).ready(function() {
$(checkboxes).filter('input[name="edit"]').attr('checked', false);
// Check Edit if Create, Update, or Delete is checked
} else if (($(this).attr('name') == 'create'
- || $(this).attr('name') == 'update'
- || $(this).attr('name') == 'delete'))
+ || $(this).attr('name') == 'update'
+ || $(this).attr('name') == 'delete'))
{
$(checkboxes).filter('input[name="edit"]').attr('checked', true);
}
@@ -597,7 +597,7 @@ $(document).ready(function() {
OC.Share.setPermissions($('#dropdown').data('item-type'),
$('#dropdown').data('item-source'),
li.data('share-type'),
- li.data('share-with'),
+ li.attr('data-share-with'),
permissions);
});
@@ -718,9 +718,21 @@ $(document).ready(function() {
$(document).on('change', '#dropdown #expirationDate', function() {
var itemType = $('#dropdown').data('item-type');
var itemSource = $('#dropdown').data('item-source');
+
+ $(this).tipsy('hide');
+ $(this).removeClass('error');
+
$.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'setExpirationDate', itemType: itemType, itemSource: itemSource, date: $(this).val() }, function(result) {
if (!result || result.status !== 'success') {
- OC.dialogs.alert(t('core', 'Error setting expiration date'), t('core', 'Error'));
+ var expirationDateField = $('#dropdown #expirationDate');
+ if (!result.data.message) {
+ expirationDateField.attr('original-title', t('core', 'Error setting expiration date'));
+ } else {
+ expirationDateField.attr('original-title', result.data.message);
+ }
+ expirationDateField.tipsy({gravity: 'n', fade: true});
+ expirationDateField.tipsy('show');
+ expirationDateField.addClass('error');
}
});
});
@@ -770,7 +782,7 @@ $(document).ready(function() {
}
var shareType = $li.data('share-type');
- var shareWith = $li.data('share-with');
+ var shareWith = $li.attr('data-share-with');
$.post(OC.filePath('core', 'ajax', 'share.php'), {action: action, recipient: shareWith, shareType: shareType, itemSource: itemSource, itemType: itemType}, function(result) {
if (result.status !== 'success') {
diff --git a/core/js/tags.js b/core/js/tags.js
index bc6d7b4e071..bc2b42bf5ff 100644
--- a/core/js/tags.js
+++ b/core/js/tags.js
@@ -69,7 +69,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_ids_for_tag', {type: type});
+ url = OC.generateUrl('/tags/{type}/ids', {type: type});
$.getJSON(url, {tag: tag}, function(response) {
if(response.status === 'success') {
defer.resolve(response.ids);
@@ -90,7 +90,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_favorites', {type: type});
+ url = OC.generateUrl('/tags/{type}/favorites', {type: type});
$.getJSON(url, function(response) {
if(response.status === 'success') {
defer.resolve(response.ids);
@@ -111,7 +111,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_tags', {type: type});
+ url = OC.generateUrl('/tags/{type}', {type: type});
$.getJSON(url, function(response) {
if(response.status === 'success') {
defer.resolve(response.tags);
@@ -133,7 +133,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_tag', {type: type, id: id});
+ url = OC.generateUrl('/tags/{type}/tag/{id}/', {type: type, id: id});
$.post(url, {tag: tag}, function(response) {
if(response.status === 'success') {
defer.resolve(response);
@@ -157,7 +157,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_untag', {type: type, id: id});
+ url = OC.generateUrl('/tags/{type}/untag/{id}/', {type: type, id: id});
$.post(url, {tag: tag}, function(response) {
if(response.status === 'success') {
defer.resolve(response);
@@ -181,7 +181,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_favorite', {type: type, id: id});
+ url = OC.generateUrl('/tags/{type}/favorite/{id}/', {type: type, id: id});
$.post(url, function(response) {
if(response.status === 'success') {
defer.resolve(response);
@@ -205,7 +205,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_unfavorite', {type: type, id: id});
+ url = OC.generateUrl('/tags/{type}/unfavorite/{id}/', {type: type, id: id});
$.post(url, function(response) {
if(response.status === 'success') {
defer.resolve();
@@ -229,7 +229,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_add', {type: type});
+ url = OC.generateUrl('/tags/{type}/add', {type: type});
$.post(url,{tag:tag}, function(response) {
if(typeof cb == 'function') {
cb(response);
@@ -256,7 +256,7 @@ OC.Tags= {
type = type ? type : this.type;
var defer = $.Deferred(),
self = this,
- url = OC.Router.generate('core_tags_delete', {type: type});
+ url = OC.generateUrl('/tags/{type}/delete', {type: type});
if(!tags || !tags.length) {
throw new Error(t('core', 'No tags selected for deletion.'));
}
diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js
index b1193240580..d86cd81cda8 100644
--- a/core/js/tests/specHelper.js
+++ b/core/js/tests/specHelper.js
@@ -68,9 +68,14 @@ window.oc_defaults = {};
// global setup for all tests
(function setupTests() {
var fakeServer = null,
+ $testArea = null,
routesRequestStub;
beforeEach(function() {
+ // test area for elements that need absolute selector access or measure widths/heights
+ // which wouldn't work for detached or hidden elements
+ $testArea = $('<div id="testArea" style="position: absolute; width: 1280px; height: 800px; top: -3000px; left: -3000px;"></div>');
+ $('body').append($testArea);
// enforce fake XHR, tests should not depend on the server and
// must use fake responses for expected calls
fakeServer = sinon.fakeServer.create();
@@ -86,21 +91,14 @@ window.oc_defaults = {};
// make it globally available, so that other tests can define
// custom responses
window.fakeServer = fakeServer;
-
- OC.Router.routes = [];
- OC.Router.routes_request = {
- state: sinon.stub().returns('resolved'),
- done: sinon.stub()
- };
});
afterEach(function() {
- OC.Router.routes_request.state.reset();
- OC.Router.routes_request.done.reset();
-
// uncomment this to log requests
// console.log(window.fakeServer.requests);
fakeServer.restore();
+
+ $testArea.remove();
});
})();
diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js
index 478505e9287..57ea5be8be0 100644
--- a/core/js/tests/specs/coreSpec.js
+++ b/core/js/tests/specs/coreSpec.js
@@ -179,7 +179,7 @@ describe('Core base tests', function() {
});
it('Encodes special characters', function() {
expect(OC.buildQueryString({
- unicode: '汉字',
+ unicode: '汉字'
})).toEqual('unicode=%E6%B1%89%E5%AD%97');
expect(OC.buildQueryString({
b: 'spaace value',
@@ -199,22 +199,20 @@ describe('Core base tests', function() {
'booleantrue': true
})).toEqual('booleanfalse=false&booleantrue=true');
expect(OC.buildQueryString({
- 'number': 123,
+ 'number': 123
})).toEqual('number=123');
});
});
describe('Session heartbeat', function() {
var clock,
oldConfig,
- loadedStub,
routeStub,
counter;
beforeEach(function() {
clock = sinon.useFakeTimers();
oldConfig = window.oc_config;
- loadedStub = sinon.stub(OC.Router, 'registerLoadedCallback');
- routeStub = sinon.stub(OC.Router, 'generate').returns('/heartbeat');
+ routeStub = sinon.stub(OC, 'generateUrl').returns('/heartbeat');
counter = 0;
fakeServer.autoRespond = true;
@@ -227,7 +225,6 @@ describe('Core base tests', function() {
afterEach(function() {
clock.restore();
window.oc_config = oldConfig;
- loadedStub.restore();
routeStub.restore();
});
it('sends heartbeat half the session lifetime when heartbeat enabled', function() {
@@ -236,9 +233,7 @@ describe('Core base tests', function() {
session_lifetime: 300
};
window.initCore();
- expect(loadedStub.calledOnce).toEqual(true);
- loadedStub.yield();
- expect(routeStub.calledWith('heartbeat')).toEqual(true);
+ expect(routeStub.calledWith('/heartbeat')).toEqual(true);
expect(counter).toEqual(0);
@@ -264,7 +259,6 @@ describe('Core base tests', function() {
session_lifetime: 300
};
window.initCore();
- expect(loadedStub.notCalled).toEqual(true);
expect(routeStub.notCalled).toEqual(true);
expect(counter).toEqual(0);
@@ -276,5 +270,118 @@ describe('Core base tests', function() {
});
});
+ describe('Generate Url', function() {
+ it('returns absolute urls', function() {
+ expect(OC.generateUrl('heartbeat')).toEqual(OC.webroot + '/index.php/heartbeat');
+ expect(OC.generateUrl('/heartbeat')).toEqual(OC.webroot + '/index.php/heartbeat');
+ });
+ it('substitutes parameters', function() {
+ expect(OC.generateUrl('apps/files/download{file}', {file: '/Welcome.txt'})).toEqual(OC.webroot + '/index.php/apps/files/download/Welcome.txt');
+ });
+ });
+ describe('Main menu mobile toggle', function() {
+ var oldMatchMedia;
+ var $toggle;
+ var $navigation;
+
+ beforeEach(function() {
+ oldMatchMedia = OC._matchMedia;
+ // a separate method was needed because window.matchMedia
+ // cannot be stubbed due to a bug in PhantomJS:
+ // https://github.com/ariya/phantomjs/issues/12069
+ OC._matchMedia = sinon.stub();
+ $('#testArea').append('<div id="header">' +
+ '<a id="owncloud" href="#"></a>' +
+ '</div>' +
+ '<div id="navigation"></div>');
+ $toggle = $('#owncloud');
+ $navigation = $('#navigation');
+ });
+
+ afterEach(function() {
+ OC._matchMedia = oldMatchMedia;
+ });
+ it('Sets up menu toggle in mobile mode', function() {
+ OC._matchMedia.returns({matches: true});
+ window.initCore();
+ expect($toggle.hasClass('menutoggle')).toEqual(true);
+ expect($navigation.hasClass('menu')).toEqual(true);
+ });
+ it('Does not set up menu toggle in desktop mode', function() {
+ OC._matchMedia.returns({matches: false});
+ window.initCore();
+ expect($toggle.hasClass('menutoggle')).toEqual(false);
+ expect($navigation.hasClass('menu')).toEqual(false);
+ });
+ it('Switches on menu toggle when mobile mode changes', function() {
+ var mq = {matches: false};
+ OC._matchMedia.returns(mq);
+ window.initCore();
+ expect($toggle.hasClass('menutoggle')).toEqual(false);
+ mq.matches = true;
+ $(window).trigger('resize');
+ expect($toggle.hasClass('menutoggle')).toEqual(true);
+ });
+ it('Switches off menu toggle when mobile mode changes', function() {
+ var mq = {matches: true};
+ OC._matchMedia.returns(mq);
+ window.initCore();
+ expect($toggle.hasClass('menutoggle')).toEqual(true);
+ mq.matches = false;
+ $(window).trigger('resize');
+ expect($toggle.hasClass('menutoggle')).toEqual(false);
+ });
+ it('Clicking menu toggle toggles navigation in mobile mode', function() {
+ OC._matchMedia.returns({matches: true});
+ window.initCore();
+ $navigation.hide(); // normally done through media query triggered CSS
+ expect($navigation.is(':visible')).toEqual(false);
+ $toggle.click();
+ expect($navigation.is(':visible')).toEqual(true);
+ $toggle.click();
+ expect($navigation.is(':visible')).toEqual(false);
+ });
+ it('Clicking menu toggle does not toggle navigation in desktop mode', function() {
+ OC._matchMedia.returns({matches: false});
+ window.initCore();
+ expect($navigation.is(':visible')).toEqual(true);
+ $toggle.click();
+ expect($navigation.is(':visible')).toEqual(true);
+ });
+ it('Switching to mobile mode hides navigation', function() {
+ var mq = {matches: false};
+ OC._matchMedia.returns(mq);
+ window.initCore();
+ expect($navigation.is(':visible')).toEqual(true);
+ mq.matches = true;
+ $(window).trigger('resize');
+ expect($navigation.is(':visible')).toEqual(false);
+ });
+ it('Switching to desktop mode shows navigation', function() {
+ var mq = {matches: true};
+ OC._matchMedia.returns(mq);
+ window.initCore();
+ expect($navigation.is(':visible')).toEqual(false);
+ mq.matches = false;
+ $(window).trigger('resize');
+ expect($navigation.is(':visible')).toEqual(true);
+ });
+ it('Switch to desktop with opened menu then back to mobile resets toggle', function() {
+ var mq = {matches: true};
+ OC._matchMedia.returns(mq);
+ window.initCore();
+ expect($navigation.is(':visible')).toEqual(false);
+ $toggle.click();
+ expect($navigation.is(':visible')).toEqual(true);
+ mq.matches = false;
+ $(window).trigger('resize');
+ expect($navigation.is(':visible')).toEqual(true);
+ mq.matches = true;
+ $(window).trigger('resize');
+ expect($navigation.is(':visible')).toEqual(false);
+ $toggle.click();
+ expect($navigation.is(':visible')).toEqual(true);
+ });
+ });
});