commit
517f24c19a
@ -0,0 +1,202 @@ |
||||
/*! |
||||
Copyright (c) 2011, 2012 Julien Wajsberg <felash@gmail.com> |
||||
All rights reserved. |
||||
|
||||
Official repository: https://github.com/julienw/jquery-trap-input
|
||||
License is there: https://github.com/julienw/jquery-trap-input/blob/master/LICENSE
|
||||
This is version 1.2.0. |
||||
*/ |
||||
|
||||
(function( $, undefined ){ |
||||
|
||||
/* |
||||
(this comment is after the first line of code so that uglifyjs removes it) |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted without condition. |
||||
|
||||
Although that's not an obligation, I would appreciate that you provide a |
||||
link to the official repository. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED. |
||||
*/ |
||||
|
||||
/*jshint boss: true, bitwise: true, curly: true, expr: true, newcap: true, noarg: true, nonew: true, latedef: true, regexdash: true */ |
||||
|
||||
var DATA_ISTRAPPING_KEY = "trap.isTrapping"; |
||||
|
||||
function onkeypress(e) { |
||||
if (e.keyCode === 9) { |
||||
var goReverse = !!(e.shiftKey); |
||||
if (processTab(this, e.target, goReverse)) { |
||||
e.preventDefault(); |
||||
e.stopPropagation(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// will return true if we could process the tab event
|
||||
// otherwise, return false
|
||||
function processTab(container, elt, goReverse) { |
||||
var $focussable = getFocusableElementsInContainer(container), |
||||
curElt = elt, |
||||
index, nextIndex, prevIndex, lastIndex; |
||||
|
||||
do { |
||||
|
||||
index = $focussable.index(curElt); |
||||
nextIndex = index + 1; |
||||
prevIndex = index - 1; |
||||
lastIndex = $focussable.length - 1; |
||||
|
||||
switch(index) { |
||||
case -1: |
||||
return false; // that's strange, let the browser do its job
|
||||
case 0: |
||||
prevIndex = lastIndex; |
||||
break; |
||||
case lastIndex: |
||||
nextIndex = 0; |
||||
break; |
||||
} |
||||
|
||||
if (goReverse) { |
||||
nextIndex = prevIndex; |
||||
} |
||||
|
||||
curElt = $focussable.get(nextIndex); |
||||
// IE sometimes throws when an element is not visible
|
||||
try { |
||||
curElt.focus(); |
||||
} catch(e) { |
||||
} |
||||
|
||||
} while (elt === elt.ownerDocument.activeElement); |
||||
|
||||
return true;
|
||||
} |
||||
|
||||
function filterKeepSpeciallyFocusable() { |
||||
return this.tabIndex > 0; |
||||
} |
||||
|
||||
function filterKeepNormalElements() { |
||||
return !this.tabIndex; // true if no tabIndex or tabIndex == 0
|
||||
} |
||||
|
||||
function sortFocusable(a, b) { |
||||
return (a.t - b.t) || (a.i - b.i); |
||||
} |
||||
|
||||
function getFocusableElementsInContainer(container) { |
||||
var $container = $(container); |
||||
var result = [], |
||||
cnt = 0; |
||||
|
||||
fixIndexSelector.enable && fixIndexSelector.enable(); |
||||
|
||||
// leaving away command and details for now
|
||||
$container.find("a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex=0]") |
||||
.filter(":visible") |
||||
.filter(filterKeepNormalElements) |
||||
.each(function(i, val) { |
||||
result.push({ |
||||
v: val, // value
|
||||
t: 0, // tabIndex
|
||||
i: cnt++ // index for stable sort
|
||||
}); |
||||
}); |
||||
|
||||
$container |
||||
.find("[tabindex]") |
||||
.filter(":visible") |
||||
.filter(filterKeepSpeciallyFocusable) |
||||
.each(function(i, val) { |
||||
result.push({ |
||||
v: val, // value
|
||||
t: val.tabIndex, // tabIndex
|
||||
i: cnt++ // index
|
||||
}); |
||||
}); |
||||
|
||||
fixIndexSelector.disable && fixIndexSelector.disable(); |
||||
|
||||
result = $.map(result.sort(sortFocusable), // needs stable sort
|
||||
function(val) { |
||||
return val.v; |
||||
} |
||||
); |
||||
|
||||
|
||||
return $(result); |
||||
|
||||
} |
||||
|
||||
function trap() { |
||||
this.keydown(onkeypress); |
||||
this.data(DATA_ISTRAPPING_KEY, true); |
||||
return this; |
||||
} |
||||
|
||||
function untrap() { |
||||
this.unbind('keydown', onkeypress); |
||||
this.removeData(DATA_ISTRAPPING_KEY); |
||||
return this; |
||||
} |
||||
|
||||
function isTrapping() { |
||||
return !!this.data(DATA_ISTRAPPING_KEY); |
||||
} |
||||
|
||||
$.fn.extend({ |
||||
trap: trap, |
||||
untrap: untrap, |
||||
isTrapping: isTrapping |
||||
}); |
||||
|
||||
// jQuery 1.6.x tabindex attr hooks management
|
||||
// this triggers problems for tabindex attribute
|
||||
// selectors in IE7-
|
||||
// see https://github.com/julienw/jquery-trap-input/issues/3
|
||||
|
||||
var fixIndexSelector = {}; |
||||
|
||||
if ($.find.find && $.find.attr !== $.attr) { |
||||
// jQuery uses Sizzle (this is jQuery >= 1.3)
|
||||
// sizzle uses its own attribute handling (in jq 1.6.x and below)
|
||||
(function() { |
||||
var tabindexKey = "tabindex"; |
||||
var sizzleAttrHandle = $.expr.attrHandle; |
||||
|
||||
// this function comes directly from jQuery 1.7.2 (propHooks.tabIndex.get)
|
||||
// we have to put it here if we want to support jQuery < 1.6 which
|
||||
// doesn't have an attrHooks object to reference.
|
||||
function getTabindexAttr(elem) { |
||||
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
|
||||
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
|
||||
var attributeNode = elem.getAttributeNode(tabindexKey); |
||||
|
||||
return attributeNode && attributeNode.specified ? |
||||
parseInt( attributeNode.value, 10 ) : |
||||
undefined; |
||||
} |
||||
|
||||
function fixSizzleAttrHook() { |
||||
// in jQ <= 1.6.x, we add to Sizzle the attrHook from jQuery's attr method
|
||||
sizzleAttrHandle[tabindexKey] = sizzleAttrHandle.tabIndex = getTabindexAttr; |
||||
} |
||||
|
||||
function unfixSizzleAttrHook() { |
||||
delete sizzleAttrHandle[tabindexKey]; |
||||
delete sizzleAttrHandle.tabIndex; |
||||
} |
||||
|
||||
|
||||
fixIndexSelector = { |
||||
enable: fixSizzleAttrHook, |
||||
disable: unfixSizzleAttrHook |
||||
}; |
||||
})(); |
||||
} |
||||
})( jQuery ); |
@ -0,0 +1,105 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
Feature: Updating work packages |
||||
Background: |
||||
Given there is 1 user with: |
||||
| login | manager | |
||||
| firstname | the | |
||||
| lastname | manager | |
||||
And there are the following types: |
||||
| Name | Is milestone | |
||||
| Phase1 | false | |
||||
| Phase2 | false | |
||||
And there are the following project types: |
||||
| Name | |
||||
| Standard Project | |
||||
And there is 1 project with the following: |
||||
| identifier | ecookbook | |
||||
| name | ecookbook | |
||||
And the project named "ecookbook" is of the type "Standard Project" |
||||
And the following types are enabled for projects of type "Standard Project" |
||||
| Phase1 | |
||||
| Phase2 | |
||||
And there is a role "manager" |
||||
And the role "manager" may have the following rights: |
||||
| edit_work_packages | |
||||
| view_work_packages | |
||||
| manage_subtasks | |
||||
And I am working in project "ecookbook" |
||||
And the user "manager" is a "manager" |
||||
And there are the following priorities: |
||||
| name | default | |
||||
| prio1 | true | |
||||
| prio2 | | |
||||
And there are the following status: |
||||
| name | default | |
||||
| status1 | true | |
||||
| status2 | | |
||||
And the project "ecookbook" has 1 version with the following: |
||||
| name | version1 | |
||||
And the type "Phase1" has the default workflow for the role "manager" |
||||
And the type "Phase2" has the default workflow for the role "manager" |
||||
And there are the following work packages in project "ecookbook": |
||||
| subject | type | status | fixed_version | assigned_to | |
||||
| pe1 | Phase1 | status1 | version1 | manager | |
||||
| pe2 | | | | manager | |
||||
And I am already logged in as "manager" |
||||
|
||||
@javascript |
||||
Scenario: Bulk updating the fixed version of several work packages |
||||
When I go to the work package index page of the project called "ecookbook" |
||||
And I open the context menu on the work packages: |
||||
| pe1 | |
||||
| pe2 | |
||||
And I hover over ".fixed_version .context_item" |
||||
And I follow "none" within "#context-menu" |
||||
Then I should see "Successful update" |
||||
And I follow "pe1" |
||||
And I should see "deleted (version1)" |
||||
|
||||
@javascript |
||||
Scenario: Bulk updating several work packages without back url should return index |
||||
When I go to the work package index page of the project called "ecookbook" |
||||
And I open the context menu on the work packages: |
||||
| pe1 | |
||||
| pe2 | |
||||
And I follow "Edit" within "#context-menu" |
||||
And I press "Submit" |
||||
Then I should see "Work packages" within "#content" |
||||
|
||||
@javascript |
||||
Scenario: Bulk updating the fixed version of several work packages |
||||
When I go to the work package index page of the project called "ecookbook" |
||||
And I open the context menu on the work packages: |
||||
| pe1 | |
||||
| pe2 | |
||||
And I hover over ".assigned_to .context_item" |
||||
And I follow "none" within "#context-menu" |
||||
Then I should see "Successful update" |
||||
Then the attribute "assigned_to" of work package "pe1" should be "" |
Loading…
Reference in new issue