Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
34e4ef48
Commit
34e4ef48
authored
Aug 24, 2012
by
Dries
Browse files
- Patch
#1574738
by nod_: rewrite tableheader.js.
parent
316fe064
Changes
5
Hide whitespace changes
Inline
Side-by-side
core/misc/tableheader.js
View file @
34e4ef48
(
function
(
$
)
{
(
function
(
$
,
Drupal
)
{
"
use strict
"
;
...
...
@@ -6,115 +6,265 @@
* Attaches sticky table headers.
*/
Drupal
.
behaviors
.
tableHeader
=
{
attach
:
function
(
context
,
settings
)
{
attach
:
function
(
context
)
{
if
(
!
$
.
support
.
fixedPosition
)
{
return
;
}
$
(
context
).
find
(
'
table.sticky-enabled
'
).
once
(
'
tableheader
'
,
function
()
{
$
(
this
).
data
(
"
drupal-tableheader
"
,
new
Drupal
.
tableHeader
(
this
));
});
$
(
window
).
one
(
'
scroll.TableHeaderInit
'
,
{
context
:
context
},
tableHeaderInitHandler
);
}
};
function
scrollValue
(
position
)
{
return
document
.
documentElement
[
position
]
||
document
.
body
[
position
];
}
// Select and initilize sticky table headers.
function
tableHeaderInitHandler
(
e
)
{
var
$tables
=
$
(
e
.
data
.
context
).
find
(
'
table.sticky-enabled
'
).
once
(
'
tableheader
'
);
for
(
var
i
=
0
,
il
=
$tables
.
length
;
i
<
il
;
i
++
)
{
TableHeader
.
tables
.
push
(
new
TableHeader
(
$tables
[
i
]));
}
}
// Helper method to loop through tables and execute a method.
function
forTables
(
method
,
arg
)
{
var
tables
=
TableHeader
.
tables
;
for
(
var
i
=
0
,
il
=
tables
.
length
;
i
<
il
;
i
++
)
{
tables
[
i
][
method
](
arg
);
}
}
function
tableHeaderResizeHandler
(
e
)
{
forTables
(
'
recalculateSticky
'
);
}
function
tableHeaderOnScrollHandler
(
e
)
{
forTables
(
'
onScroll
'
);
}
function
tableHeaderOffsetChangeHandler
(
e
)
{
// Compute the new offset value.
TableHeader
.
computeOffsetTop
();
forTables
(
'
stickyPosition
'
,
TableHeader
.
offsetTop
);
}
// Bind event that need to change all tables.
$
(
window
).
on
({
/**
* When resizing table width and offset top can change, recalculate everything.
*/
'
resize.TableHeader
'
:
tableHeaderResizeHandler
,
/**
* Bind only one event to take care of calling all scroll callbacks.
*/
'
scroll.TableHeader
'
:
tableHeaderOnScrollHandler
});
// Bind to custom Drupal events.
$
(
document
).
on
({
/**
* Recalculate columns width when window is resized and when show/hide
* weight is triggered.
*/
'
columnschange.TableHeader
'
:
tableHeaderResizeHandler
,
/**
* Offset value vas changed by a third party script.
*/
'
offsettopchange.TableHeader
'
:
tableHeaderOffsetChangeHandler
});
/**
* Constructor for the tableHeader object. Provides sticky table headers.
*
* TableHeader will make the current table header stick to the top of the page
* if the table is very long.
*
* Fire a custom "topoffsetchange" event to make TableHeader compute the
* new offset value from the "data-offset-top" attributes of relevant elements.
*
* @param table
* DOM object for the table to add a sticky header to.
*
* @constructor
*/
Drupal
.
tableHeader
=
function
(
table
)
{
var
self
=
this
;
function
TableHeader
(
table
)
{
var
$table
=
$
(
table
);
this
.
originalTable
=
$table
;
this
.
originalHeader
=
$table
.
children
(
'
thead
'
);
this
.
originalHeaderCells
=
this
.
originalHeader
.
find
(
'
> tr > th
'
);
this
.
$
originalTable
=
$table
;
this
.
$
originalHeader
=
$table
.
children
(
'
thead
'
);
this
.
$
originalHeaderCells
=
this
.
$
originalHeader
.
find
(
'
> tr > th
'
);
this
.
displayWeight
=
null
;
this
.
$originalTable
.
addClass
(
'
sticky-table
'
);
this
.
tableHeight
=
$table
[
0
].
clientHeight
;
this
.
tableOffset
=
this
.
$originalTable
.
offset
();
// React to columns change to avoid making checks in the scroll callback.
this
.
originalTable
.
bind
(
'
columnschange
'
,
function
(
e
,
display
)
{
// This will force header size to be calculated on scroll.
self
.
widthCalculated
=
(
self
.
displayWeight
!==
null
&&
self
.
displayWeight
===
display
);
self
.
displayWeight
=
display
;
this
.
$originalTable
.
bind
(
'
columnschange
'
,
{
tableHeader
:
this
},
function
(
e
,
display
)
{
var
tableHeader
=
e
.
data
.
tableHeader
;
if
(
tableHeader
.
displayWeight
===
null
||
tableHeader
.
displayWeight
!==
display
)
{
tableHeader
.
recalculateSticky
();
}
tableHeader
.
displayWeight
=
display
;
});
// Clone the table header so it inherits original jQuery properties. Hide
// the table to avoid a flash of the header clone upon page load.
this
.
stickyTable
=
$
(
'
<table class="sticky-header"/>
'
)
.
insertBefore
(
this
.
originalTable
)
.
css
({
position
:
'
fixed
'
,
top
:
'
0px
'
});
this
.
stickyHeader
=
this
.
originalHeader
.
clone
(
true
)
.
hide
()
.
appendTo
(
this
.
stickyTable
);
this
.
stickyHeaderCells
=
this
.
stickyHeader
.
find
(
'
> tr > th
'
);
this
.
originalTable
.
addClass
(
'
sticky-table
'
);
$
(
window
)
.
bind
(
'
scroll.drupal-tableheader
'
,
$
.
proxy
(
this
,
'
eventhandlerRecalculateStickyHeader
'
))
.
bind
(
'
resize.drupal-tableheader
'
,
{
calculateWidth
:
true
},
$
.
proxy
(
this
,
'
eventhandlerRecalculateStickyHeader
'
))
// Make sure the anchor being scrolled into view is not hidden beneath the
// sticky table header. Adjust the scrollTop if it does.
.
bind
(
'
drupalDisplaceAnchor.drupal-tableheader
'
,
function
()
{
window
.
scrollBy
(
0
,
-
self
.
stickyTable
.
outerHeight
());
})
// Make sure the element being focused is not hidden beneath the sticky
// table header. Adjust the scrollTop if it does.
.
bind
(
'
drupalDisplaceFocus.drupal-tableheader
'
,
function
(
event
)
{
if
(
self
.
stickyVisible
&&
event
.
clientY
<
(
self
.
stickyOffsetTop
+
self
.
stickyTable
.
outerHeight
())
&&
event
.
$target
.
closest
(
'
sticky-header
'
).
length
===
0
)
{
window
.
scrollBy
(
0
,
-
self
.
stickyTable
.
outerHeight
());
}
})
.
triggerHandler
(
'
resize.drupal-tableheader
'
);
// We hid the header to avoid it showing up erroneously on page load;
// we need to unhide it now so that it will show up when expected.
this
.
stickyHeader
.
show
();
};
// Create and display sticky header.
this
.
createSticky
();
}
/**
* Event handler: recalculates position of the sticky table header.
*
* @param event
* Event being triggered.
* Store the state of TableHeader.
*/
Drupal
.
tableHeader
.
prototype
.
eventhandlerRecalculateStickyHeader
=
function
(
event
)
{
var
self
=
this
;
var
calculateWidth
=
event
.
data
&&
event
.
data
.
calculateWidth
;
// Reset top position of sticky table headers to the current top offset.
this
.
stickyOffsetTop
=
Drupal
.
settings
.
tableHeaderOffset
?
eval
(
Drupal
.
settings
.
tableHeaderOffset
+
'
()
'
)
:
0
;
this
.
stickyTable
.
css
(
'
top
'
,
this
.
stickyOffsetTop
+
'
px
'
);
// Save positioning data.
var
viewHeight
=
document
.
documentElement
.
scrollHeight
||
document
.
body
.
scrollHeight
;
if
(
calculateWidth
||
this
.
viewHeight
!==
viewHeight
)
{
this
.
viewHeight
=
viewHeight
;
this
.
vPosition
=
this
.
originalTable
.
offset
().
top
-
4
-
this
.
stickyOffsetTop
;
this
.
hPosition
=
this
.
originalTable
.
offset
().
left
;
this
.
vLength
=
this
.
originalTable
[
0
].
clientHeight
-
100
;
calculateWidth
=
true
;
$
.
extend
(
TableHeader
,
{
/**
* This will store the state of all processed tables.
*
* @type {Array}
*/
tables
:
[],
/**
* Cache of computed offset value.
*
* @type {Number}
*/
offsetTop
:
0
,
/**
* Sum all [data-offset-top] values and cache it.
*/
computeOffsetTop
:
function
()
{
var
$offsets
=
$
(
'
[data-offset-top]
'
);
var
value
,
sum
=
0
;
for
(
var
i
=
0
,
il
=
$offsets
.
length
;
i
<
il
;
i
++
)
{
value
=
parseInt
(
$offsets
[
i
].
getAttribute
(
'
data-offset-top
'
),
10
);
sum
+=
!
isNaN
(
value
)
?
value
:
0
;
}
this
.
offsetTop
=
sum
;
return
sum
;
}
});
/**
* Extend TableHeader prototype.
*/
$
.
extend
(
TableHeader
.
prototype
,
{
/**
* Minimum height in pixels for the table to have a sticky header.
*/
minHeight
:
100
,
/**
* Absolute position of the table on the page.
*/
tableOffset
:
null
,
/**
* Absolute position of the table on the page.
*/
tableHeight
:
null
,
/**
* Boolean storing the sticky header visibility state.
*/
stickyVisible
:
false
,
/**
* Create the duplicate header.
*/
createSticky
:
function
()
{
// Clone the table header so it inherits original jQuery properties.
var
$stickyHeader
=
this
.
$originalHeader
.
clone
(
true
);
// Hide the table to avoid a flash of the header clone upon page load.
this
.
$stickyTable
=
$
(
'
<table class="sticky-header"/>
'
)
.
css
({
visibility
:
'
hidden
'
,
position
:
'
fixed
'
,
top
:
'
0px
'
})
.
append
(
$stickyHeader
)
.
insertBefore
(
this
.
$originalTable
);
this
.
$stickyHeaderCells
=
$stickyHeader
.
find
(
'
> tr > th
'
);
// Initialize all computations.
this
.
recalculateSticky
();
},
// Track horizontal positioning relative to the viewport and set visibility.
var
hScroll
=
document
.
documentElement
.
scrollLeft
||
document
.
body
.
scrollLeft
;
var
vOffset
=
(
document
.
documentElement
.
scrollTop
||
document
.
body
.
scrollTop
)
-
this
.
vPosition
;
this
.
stickyVisible
=
vOffset
>
0
&&
vOffset
<
this
.
vLength
;
this
.
stickyTable
.
css
({
left
:
(
-
hScroll
+
this
.
hPosition
)
+
'
px
'
,
visibility
:
this
.
stickyVisible
?
'
visible
'
:
'
hidden
'
});
/**
* Set absolute position of sticky.
*
* @param offsetTop
* @param offsetLeft
*/
stickyPosition
:
function
(
offsetTop
,
offsetLeft
)
{
var
css
=
{};
if
(
!
isNaN
(
offsetTop
))
{
css
.
top
=
offsetTop
+
'
px
'
;
}
if
(
!
isNaN
(
offsetLeft
))
{
css
.
left
=
(
this
.
tableOffset
.
left
-
offsetLeft
)
+
'
px
'
;
}
return
this
.
$stickyTable
.
css
(
css
);
},
/**
* Returns true if sticky is currently visible.
*/
checkStickyVisible
:
function
()
{
var
scrollTop
=
scrollValue
(
'
scrollTop
'
);
var
tableTop
=
this
.
tableOffset
.
top
-
TableHeader
.
offsetTop
;
var
tableBottom
=
tableTop
+
this
.
tableHeight
;
var
visible
=
false
;
if
(
tableTop
<
scrollTop
&&
scrollTop
<
(
tableBottom
-
this
.
minHeight
))
{
visible
=
true
;
}
this
.
stickyVisible
=
visible
;
return
visible
;
},
// Only perform expensive calculations if the sticky header is actually
// visible or when forced.
if
(
this
.
stickyVisible
&&
(
calculateWidth
||
!
this
.
widthCalculated
))
{
this
.
widthCalculated
=
true
;
/**
* Check if sticky header should be displayed.
*
* This function is throttled to once every 250ms to avoid unnecessary calls.
*
* @param event
*/
onScroll
:
function
(
e
)
{
this
.
checkStickyVisible
();
// Track horizontal positioning relative to the viewport.
this
.
stickyPosition
(
null
,
scrollValue
(
'
scrollLeft
'
));
this
.
$stickyTable
.
css
(
'
visibility
'
,
this
.
stickyVisible
?
'
visible
'
:
'
hidden
'
);
},
/**
* Event handler: recalculates position of the sticky table header.
*
* @param event
* Event being triggered.
*/
recalculateSticky
:
function
(
event
)
{
// Update table size.
this
.
tableHeight
=
this
.
$originalTable
[
0
].
clientHeight
;
// Update offset top.
TableHeader
.
computeOffsetTop
();
this
.
tableOffset
=
this
.
$originalTable
.
offset
();
this
.
stickyPosition
(
TableHeader
.
offsetTop
);
// Update columns width.
var
$that
=
null
;
var
$stickyCell
=
null
;
var
display
=
null
;
// Resize header and its cell widths.
// Only apply width to visible table cells. This prevents the header from
// displaying incorrectly when the sticky header is no longer visible.
for
(
var
i
=
0
,
il
=
this
.
originalHeaderCells
.
length
;
i
<
il
;
i
+=
1
)
{
$that
=
$
(
this
.
originalHeaderCells
[
i
]);
$stickyCell
=
this
.
stickyHeaderCells
.
eq
(
$that
.
index
());
for
(
var
i
=
0
,
il
=
this
.
$
originalHeaderCells
.
length
;
i
<
il
;
i
++
)
{
$that
=
$
(
this
.
$
originalHeaderCells
[
i
]);
$stickyCell
=
this
.
$
stickyHeaderCells
.
eq
(
$that
.
index
());
display
=
$that
.
css
(
'
display
'
);
if
(
display
!==
'
none
'
)
{
$stickyCell
.
css
({
'
width
'
:
$that
.
css
(
'
width
'
),
'
display
'
:
display
});
...
...
@@ -123,8 +273,11 @@ Drupal.tableHeader.prototype.eventhandlerRecalculateStickyHeader = function (eve
$stickyCell
.
css
(
'
display
'
,
'
none
'
);
}
}
this
.
stickyTable
.
css
(
'
width
'
,
this
.
originalTable
.
css
(
'
w
idth
'
));
this
.
$
stickyTable
.
css
(
'
width
'
,
this
.
$
originalTable
.
outerW
idth
(
));
}
};
});
// Expose constructor in the public space.
Drupal
.
TableHeader
=
TableHeader
;
}
)
(
jQuery
);
}(
jQuery
,
Drupal
)
);
core/modules/overlay/overlay-child.js
View file @
34e4ef48
...
...
@@ -174,23 +174,11 @@ Drupal.overlayChild.behaviors.shortcutAddLink = function (context, settings) {
});
};
/**
* Use displacement from parent window.
*/
Drupal
.
overlayChild
.
behaviors
.
alterTableHeaderOffset
=
function
(
context
,
settings
)
{
if
(
Drupal
.
settings
.
tableHeaderOffset
)
{
Drupal
.
overlayChild
.
prevTableHeaderOffset
=
Drupal
.
settings
.
tableHeaderOffset
;
}
Drupal
.
settings
.
tableHeaderOffset
=
'
Drupal.overlayChild.tableHeaderOffset
'
;
};
/**
* Callback for Drupal.settings.tableHeaderOffset.
*/
Drupal
.
overlayChild
.
tableHeaderOffset
=
function
()
{
var
topOffset
=
Drupal
.
overlayChild
.
prevTableHeaderOffset
?
eval
(
Drupal
.
overlayChild
.
prevTableHeaderOffset
+
'
()
'
)
:
0
;
return
topOffset
+
parseInt
(
$
(
document
.
body
).
css
(
'
marginTop
'
));
};
// Workaround because of the way jQuery events works.
// jQuery from the parent frame needs to be used to catch this event.
parent
.
jQuery
(
document
).
bind
(
'
offsettopchange
'
,
function
()
{
// Fires an event that the child iframe can listen to.
$
(
document
).
trigger
(
'
offsettopchange
'
);
});
})(
jQuery
);
core/modules/overlay/overlay-parent.js
View file @
34e4ef48
...
...
@@ -433,6 +433,12 @@ Drupal.overlay.eventhandlerAlterDisplacedElements = function (event) {
$
(
this
.
iframeWindow
.
document
.
body
).
css
({
marginTop
:
Drupal
.
overlay
.
getDisplacement
(
'
top
'
),
marginBottom
:
Drupal
.
overlay
.
getDisplacement
(
'
bottom
'
)
}).
attr
(
'
data-offset-top
'
,
Drupal
.
overlay
.
getDisplacement
(
'
top
'
));
$
(
document
).
bind
(
'
offsettopchange
'
,
function
()
{
var
iframeDocument
=
Drupal
.
overlay
.
iframeWindow
.
document
;
$
(
iframeDocument
.
body
).
attr
(
'
data-offset-top
'
,
Drupal
.
overlay
.
getDisplacement
(
'
top
'
));
$
(
iframeDocument
).
trigger
(
'
offsettopchange
'
);
});
var
documentHeight
=
this
.
iframeWindow
.
document
.
body
.
clientHeight
;
...
...
core/modules/toolbar/toolbar.js
View file @
34e4ef48
...
...
@@ -8,18 +8,23 @@ Drupal.toolbar = Drupal.toolbar || {};
* Attach toggling behavior and notify the overlay of the toolbar.
*/
Drupal
.
behaviors
.
toolbar
=
{
attach
:
function
(
context
)
{
var
$context
=
$
(
context
);
// Set the initial state of the toolbar.
$context
.
find
(
'
#toolbar
'
).
once
(
'
toolbar
'
,
Drupal
.
toolbar
.
init
);
attach
:
function
(
context
,
settings
)
{
var
$toolbar
=
$
(
'
#toolbar
'
).
once
(
'
toolbar
'
);
if
(
$toolbar
.
length
)
{
// Toggling toolbar drawer.
$context
.
find
(
'
#toolbar a.toggle
'
).
once
(
'
toolbar-toggle
'
).
click
(
function
(
e
)
{
Drupal
.
toolbar
.
toggle
();
// Allow resize event handlers to recalculate sizes/positions.
$
(
window
).
triggerHandler
(
'
resize
'
);
return
false
;
});
// Set the initial state of the toolbar.
Drupal
.
toolbar
.
init
();
$
(
window
).
on
(
'
resize.toolbar
'
,
Drupal
.
toolbar
.
height
);
// Toggling toolbar drawer.
$toolbar
.
find
(
'
a.toggle
'
).
once
(
'
toolbar-toggle
'
).
click
(
function
(
e
)
{
e
.
preventDefault
();
Drupal
.
toolbar
.
toggle
();
// Allow resize event handlers to recalculate sizes/positions.
$
(
window
).
triggerHandler
(
'
resize
'
);
});
}
}
};
...
...
@@ -59,6 +64,8 @@ Drupal.toolbar.collapse = function() {
expires
:
36500
}
);
Drupal
.
toolbar
.
height
();
$
(
document
).
trigger
(
'
offsettopchange
'
);
};
/**
...
...
@@ -81,6 +88,8 @@ Drupal.toolbar.expand = function() {
expires
:
36500
}
);
Drupal
.
toolbar
.
height
();
$
(
document
).
trigger
(
'
offsettopchange
'
);
};
/**
...
...
@@ -96,8 +105,10 @@ Drupal.toolbar.toggle = function() {
};
Drupal
.
toolbar
.
height
=
function
()
{
// @TODO this needs to be cached outside this function.
var
$toolbar
=
$
(
'
#toolbar
'
);
var
height
=
$toolbar
.
outerHeight
();
$toolbar
.
attr
(
'
data-offset-top
'
,
height
);
return
height
;
};
...
...
core/modules/toolbar/toolbar.module
View file @
34e4ef48
...
...
@@ -194,10 +194,6 @@ function toolbar_view() {
'#attached'
=>
array
(
'js'
=>
array
(
$module_path
.
'/toolbar.js'
,
array
(
'data'
=>
array
(
'tableHeaderOffset'
=>
'Drupal.toolbar.height'
),
'type'
=>
'setting'
),
),
'css'
=>
array
(
$module_path
.
'/toolbar.css'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment