Merge remote-tracking branch 'origin/master' into git-raw-workhorse
This commit is contained in:
commit
15a1acb479
21 changed files with 414 additions and 32 deletions
|
@ -4,6 +4,7 @@ v 8.5.0 (unreleased)
|
|||
- Ensure rake tasks that don't need a DB connection can be run without one
|
||||
- Add "visibility" flag to GET /projects api endpoint
|
||||
- Ignore binary files in code search to prevent Error 500 (Stan Hu)
|
||||
- Render sanitized SVG images (Stan Hu)
|
||||
- Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push
|
||||
- New UI for pagination
|
||||
- Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet
|
||||
|
@ -14,7 +15,9 @@ v 8.5.0 (unreleased)
|
|||
- Display 404 error on group not found
|
||||
- Track project import failure
|
||||
- Fix visibility level text in admin area (Zeger-Jan van de Weg)
|
||||
- Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg)
|
||||
- Update the ExternalIssue regex pattern (Blake Hitchcock)
|
||||
- Optimized performance of finding issues to be closed by a merge request
|
||||
- Revert "Add IP check against DNSBLs at account sign-up"
|
||||
- Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead
|
||||
- Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead
|
||||
|
@ -46,7 +49,6 @@ v 8.4.1
|
|||
and Nokogiri (1.6.7.2)
|
||||
- Fix redirect loop during import
|
||||
- Fix diff highlighting for all syntax themes
|
||||
- Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg)
|
||||
- Delete project and associations in a background worker
|
||||
|
||||
v 8.4.0
|
||||
|
|
|
@ -177,6 +177,26 @@ is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
|
|||
issues or chunks. You can simply not set the weight of a parent issue and set
|
||||
weights to children issues.
|
||||
|
||||
### Regression issues
|
||||
|
||||
Every monthly release has a corresponding issue on the CE issue tracker to keep
|
||||
track of functionality broken by that release and any fixes that need to be
|
||||
included in a patch release (see [8.3 Regressions] as an example).
|
||||
|
||||
As outlined in the issue description, the intended workflow is to post one note
|
||||
with a reference to an issue describing the regression, and then to update that
|
||||
note with a reference to the merge request that fixes it as it becomes available.
|
||||
|
||||
If you're a contributor who doesn't have the required permissions to update
|
||||
other users' notes, please post a new note with a reference to both the issue
|
||||
and the merge request.
|
||||
|
||||
The release manager will [update the notes] in the regression issue as fixes are
|
||||
addressed.
|
||||
|
||||
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
|
||||
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
|
||||
|
||||
## Merge requests
|
||||
|
||||
We welcome merge requests with fixes and improvements to GitLab code, tests,
|
||||
|
|
3
Gemfile
3
Gemfile
|
@ -179,6 +179,9 @@ gem "underscore-rails", "~> 1.8.0"
|
|||
gem "sanitize", '~> 2.0'
|
||||
gem 'babosa', '~> 1.0.2'
|
||||
|
||||
# Sanitizes SVG input
|
||||
gem "loofah", "~> 2.0.3"
|
||||
|
||||
# Protect against bruteforcing
|
||||
gem "rack-attack", '~> 4.3.1'
|
||||
|
||||
|
|
|
@ -953,6 +953,7 @@ DEPENDENCIES
|
|||
jquery-ui-rails (~> 5.0.0)
|
||||
kaminari (~> 0.16.3)
|
||||
letter_opener (~> 1.1.2)
|
||||
loofah (~> 2.0.3)
|
||||
mail_room (~> 0.6.1)
|
||||
method_source (~> 0.8)
|
||||
minitest (~> 5.7.0)
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
#= require jquery.ba-resize
|
||||
#= require autosize
|
||||
|
||||
$ ->
|
||||
autosize($('.js-autosize'))
|
||||
$fields = $('.js-autosize')
|
||||
|
||||
$fields.on 'autosize:resized', ->
|
||||
$field = $(@)
|
||||
$field.data('height', $field.outerHeight())
|
||||
|
||||
$fields.on 'resize.autosize', ->
|
||||
$field = $(@)
|
||||
|
||||
if $field.data('height') != $field.outerHeight()
|
||||
$field.data('height', $field.outerHeight())
|
||||
autosize.destroy($field)
|
||||
$field.css('max-height', window.outerHeight)
|
||||
|
||||
autosize($fields)
|
||||
autosize.update($fields)
|
||||
|
||||
$fields.css('resize', 'vertical')
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
background: #FFF;
|
||||
border: 1px solid #ddd;
|
||||
min-height: 140px;
|
||||
max-height: 430px;
|
||||
max-height: 500px;
|
||||
padding: 5px;
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
.edit_note {
|
||||
.markdown-area {
|
||||
min-height: 140px;
|
||||
max-height: 430px;
|
||||
max-height: 500px;
|
||||
}
|
||||
.note-form-actions {
|
||||
background: transparent;
|
||||
|
|
|
@ -126,4 +126,16 @@ module BlobHelper
|
|||
blob.size
|
||||
end
|
||||
end
|
||||
|
||||
def blob_svg?(blob)
|
||||
blob.language && blob.language.name == 'SVG'
|
||||
end
|
||||
|
||||
# SVGs can contain malicious JavaScript; only include whitelisted
|
||||
# elements and attributes. Note that this whitelist is by no means complete
|
||||
# and may omit some elements.
|
||||
def sanitize_svg(blob)
|
||||
blob.data = Loofah.scrub_fragment(blob.data, :strip).to_xml
|
||||
blob
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ class EmailRejectionMailer < BaseMailer
|
|||
subject: "[Rejected] #{@original_message.subject}"
|
||||
}
|
||||
|
||||
headers['Message-ID'] = SecureRandom.hex
|
||||
headers['Message-ID'] = "<#{SecureRandom.hex}@#{Gitlab.config.gitlab.host}>"
|
||||
headers['In-Reply-To'] = @original_message.message_id
|
||||
headers['References'] = @original_message.message_id
|
||||
|
||||
|
|
|
@ -346,10 +346,10 @@ class MergeRequest < ActiveRecord::Base
|
|||
# Return the set of issues that will be closed if this merge request is accepted.
|
||||
def closes_issues(current_user = self.author)
|
||||
if target_branch == project.default_branch
|
||||
issues = commits.flat_map { |c| c.closes_issues(current_user) }
|
||||
issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user).
|
||||
closed_by_message(description))
|
||||
issues.uniq(&:id)
|
||||
messages = commits.map(&:safe_message) << description
|
||||
|
||||
Gitlab::ClosingIssueExtractor.new(project, current_user).
|
||||
closed_by_message(messages.join("\n"))
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
|
|
@ -35,7 +35,10 @@
|
|||
- if blob.lfs_pointer?
|
||||
= render "download", blob: blob
|
||||
- elsif blob.text?
|
||||
= render "text", blob: blob
|
||||
- if blob_svg?(blob)
|
||||
= render "image", blob: sanitize_svg(blob)
|
||||
- else
|
||||
= render "text", blob: blob
|
||||
- elsif blob.image?
|
||||
= render "image", blob: blob
|
||||
- else
|
||||
|
|
|
@ -49,12 +49,14 @@ if Gitlab::Metrics.enabled?
|
|||
config.instrument_instance_methods(Gitlab::Shell)
|
||||
|
||||
config.instrument_methods(Gitlab::Git)
|
||||
config.instrument_instance_methods(Gitlab::Git::Repository)
|
||||
|
||||
Gitlab::Git.constants.each do |name|
|
||||
const = Gitlab::Git.const_get(name)
|
||||
|
||||
config.instrument_methods(const) if const.is_a?(Module)
|
||||
next unless const.is_a?(Module)
|
||||
|
||||
config.instrument_methods(const)
|
||||
config.instrument_instance_methods(const)
|
||||
end
|
||||
|
||||
Dir[Rails.root.join('app', 'finders', '*.rb')].each do |path|
|
||||
|
@ -62,6 +64,16 @@ if Gitlab::Metrics.enabled?
|
|||
|
||||
config.instrument_instance_methods(const)
|
||||
end
|
||||
|
||||
[
|
||||
:Blame, :Branch, :BranchCollection, :Blob, :Commit, :Diff, :Repository,
|
||||
:Tag, :TagCollection, :Tree
|
||||
].each do |name|
|
||||
const = Rugged.const_get(name)
|
||||
|
||||
config.instrument_methods(const)
|
||||
config.instrument_instance_methods(const)
|
||||
end
|
||||
end
|
||||
|
||||
GC::Profiler.enable
|
||||
|
|
|
@ -18,7 +18,7 @@ GET /ci/projects
|
|||
Returns:
|
||||
|
||||
```json
|
||||
[
|
||||
[
|
||||
{
|
||||
"id" : 271,
|
||||
"name" : "gitlabhq",
|
||||
|
|
|
@ -320,3 +320,13 @@ Feature: Project Source Browse Files
|
|||
Then I should see download link and object size
|
||||
And I should not see lfs pointer details
|
||||
And I should see buttons for allowed commands
|
||||
|
||||
@javascript
|
||||
Scenario: I preview an SVG file
|
||||
Given I click on "Upload file" link in repo
|
||||
And I upload a new SVG file
|
||||
And I fill the upload file commit message
|
||||
And I fill the new branch name
|
||||
And I click on "Upload file"
|
||||
Given I visit the SVG file
|
||||
Then I can see the new rendered SVG image
|
||||
|
|
|
@ -351,6 +351,19 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
|
|||
expect(page).to have_content "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
|
||||
end
|
||||
|
||||
# SVG files
|
||||
step 'I upload a new SVG file' do
|
||||
drop_in_dropzone test_svg_file
|
||||
end
|
||||
|
||||
step 'I visit the SVG file' do
|
||||
visit namespace_project_blob_path(@project.namespace, @project, 'new_branch_name/logo_sample.svg')
|
||||
end
|
||||
|
||||
step 'I can see the new rendered SVG image' do
|
||||
expect(find('.file-content')).to have_css('img')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_new_content
|
||||
|
@ -410,4 +423,8 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
|
|||
def test_image_file
|
||||
File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')
|
||||
end
|
||||
|
||||
def test_svg_file
|
||||
File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,19 +44,19 @@ module Gitlab
|
|||
|
||||
|
||||
def file_name_regex
|
||||
@file_name_regex ||= /\A[a-zA-Z0-9_\-\.]*\z/.freeze
|
||||
@file_name_regex ||= /\A[a-zA-Z0-9_\-\.\@]*\z/.freeze
|
||||
end
|
||||
|
||||
def file_name_regex_message
|
||||
"can contain only letters, digits, '_', '-' and '.'. "
|
||||
"can contain only letters, digits, '_', '-', '@' and '.'. "
|
||||
end
|
||||
|
||||
def file_path_regex
|
||||
@file_path_regex ||= /\A[a-zA-Z0-9_\-\.\/]*\z/.freeze
|
||||
@file_path_regex ||= /\A[a-zA-Z0-9_\-\.\/\@]*\z/.freeze
|
||||
end
|
||||
|
||||
def file_path_regex_message
|
||||
"can contain only letters, digits, '_', '-' and '.'. Separate directories with a '/'. "
|
||||
"can contain only letters, digits, '_', '-', '@' and '.'. Separate directories with a '/'. "
|
||||
end
|
||||
|
||||
|
||||
|
|
27
spec/fixtures/logo_sample.svg
vendored
Normal file
27
spec/fixtures/logo_sample.svg
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="210px" height="210px" viewBox="0 0 210 210" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: Sketch 3.3.2 (12043) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Slice 1</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<script>alert('FAIL')</script>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="logo" sketch:type="MSLayerGroup" transform="translate(0.000000, 10.000000)">
|
||||
<g id="Page-1" sketch:type="MSShapeGroup">
|
||||
<g id="Fill-1-+-Group-24">
|
||||
<g id="Group-24">
|
||||
<g id="Group">
|
||||
<path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329" class="tanuki-shape"></path>
|
||||
<path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26" class="tanuki-shape"></path>
|
||||
<path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326" class="tanuki-shape"></path>
|
||||
<path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329" class="tanuki-shape"></path>
|
||||
<path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26" class="tanuki-shape"></path>
|
||||
<path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326" class="tanuki-shape"></path>
|
||||
<path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329" class="tanuki-shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
11
spec/javascripts/behaviors/autosize_spec.js.coffee
Normal file
11
spec/javascripts/behaviors/autosize_spec.js.coffee
Normal file
|
@ -0,0 +1,11 @@
|
|||
#= require behaviors/autosize
|
||||
|
||||
describe 'Autosize behavior', ->
|
||||
beforeEach ->
|
||||
fixture.set('<textarea class="js-autosize" style="resize: vertical"></textarea>')
|
||||
|
||||
it 'does not overwrite the resize property', ->
|
||||
load()
|
||||
expect($('textarea')).toHaveCss(resize: 'vertical')
|
||||
|
||||
load = -> $(document).trigger('page:load')
|
|
@ -21,4 +21,12 @@ describe Gitlab::Regex, lib: true do
|
|||
it { expect('Dash – is this').to match(Gitlab::Regex.project_name_regex) }
|
||||
it { expect('?gitlab').not_to match(Gitlab::Regex.project_name_regex) }
|
||||
end
|
||||
|
||||
describe 'file name regex' do
|
||||
it { expect('foo@bar').to match(Gitlab::Regex.file_name_regex) }
|
||||
end
|
||||
|
||||
describe 'file path regex' do
|
||||
it { expect('foo@/bar').to match(Gitlab::Regex.file_path_regex) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -137,9 +137,10 @@ describe MergeRequest, models: true do
|
|||
describe 'detection of issues to be closed' do
|
||||
let(:issue0) { create :issue, project: subject.project }
|
||||
let(:issue1) { create :issue, project: subject.project }
|
||||
let(:commit0) { double('commit0', closes_issues: [issue0]) }
|
||||
let(:commit1) { double('commit1', closes_issues: [issue0]) }
|
||||
let(:commit2) { double('commit2', closes_issues: [issue1]) }
|
||||
|
||||
let(:commit0) { double('commit0', safe_message: "Fixes #{issue0.to_reference}") }
|
||||
let(:commit1) { double('commit1', safe_message: "Fixes #{issue0.to_reference}") }
|
||||
let(:commit2) { double('commit2', safe_message: "Fixes #{issue1.to_reference}") }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:commits).and_return([commit0, commit1, commit2])
|
||||
|
@ -149,7 +150,9 @@ describe MergeRequest, models: true do
|
|||
allow(subject.project).to receive(:default_branch).
|
||||
and_return(subject.target_branch)
|
||||
|
||||
expect(subject.closes_issues).to eq([issue0, issue1].sort_by(&:id))
|
||||
closed = subject.closes_issues
|
||||
|
||||
expect(closed).to include(issue0, issue1)
|
||||
end
|
||||
|
||||
it 'only lists issues as to be closed if it targets the default branch' do
|
||||
|
@ -167,17 +170,6 @@ describe MergeRequest, models: true do
|
|||
|
||||
expect(subject.closes_issues).to include(issue2)
|
||||
end
|
||||
|
||||
context 'for a project with JIRA integration' do
|
||||
let(:issue0) { JiraIssue.new('JIRA-123', subject.project) }
|
||||
let(:issue1) { JiraIssue.new('FOOBAR-4567', subject.project) }
|
||||
|
||||
it 'returns sorted JiraIssues' do
|
||||
allow(subject.project).to receive_messages(default_branch: subject.target_branch)
|
||||
|
||||
expect(subject.closes_issues).to eq([issue0, issue1])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#work_in_progress?" do
|
||||
|
|
246
vendor/assets/javascripts/jquery.ba-resize.js
vendored
Normal file
246
vendor/assets/javascripts/jquery.ba-resize.js
vendored
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*!
|
||||
* jQuery resize event - v1.1 - 3/14/2010
|
||||
* http://benalman.com/projects/jquery-resize-plugin/
|
||||
*
|
||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://benalman.com/about/license/
|
||||
*/
|
||||
|
||||
// Script: jQuery resize event
|
||||
//
|
||||
// *Version: 1.1, Last updated: 3/14/2010*
|
||||
//
|
||||
// Project Home - http://benalman.com/projects/jquery-resize-plugin/
|
||||
// GitHub - http://github.com/cowboy/jquery-resize/
|
||||
// Source - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.js
|
||||
// (Minified) - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.min.js (1.0kb)
|
||||
//
|
||||
// About: License
|
||||
//
|
||||
// Copyright (c) 2010 "Cowboy" Ben Alman,
|
||||
// Dual licensed under the MIT and GPL licenses.
|
||||
// http://benalman.com/about/license/
|
||||
//
|
||||
// About: Examples
|
||||
//
|
||||
// This working example, complete with fully commented code, illustrates a few
|
||||
// ways in which this plugin can be used.
|
||||
//
|
||||
// resize event - http://benalman.com/code/projects/jquery-resize/examples/resize/
|
||||
//
|
||||
// About: Support and Testing
|
||||
//
|
||||
// Information about what version or versions of jQuery this plugin has been
|
||||
// tested with, what browsers it has been tested in, and where the unit tests
|
||||
// reside (so you can test it yourself).
|
||||
//
|
||||
// jQuery Versions - 1.3.2, 1.4.1, 1.4.2
|
||||
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.1.
|
||||
// Unit Tests - http://benalman.com/code/projects/jquery-resize/unit/
|
||||
//
|
||||
// About: Release History
|
||||
//
|
||||
// 1.1 - (3/14/2010) Fixed a minor bug that was causing the event to trigger
|
||||
// immediately after bind in some circumstances. Also changed $.fn.data
|
||||
// to $.data to improve performance.
|
||||
// 1.0 - (2/10/2010) Initial release
|
||||
|
||||
(function($,window,undefined){
|
||||
'$:nomunge'; // Used by YUI compressor.
|
||||
|
||||
// A jQuery object containing all non-window elements to which the resize
|
||||
// event is bound.
|
||||
var elems = $([]),
|
||||
|
||||
// Extend $.resize if it already exists, otherwise create it.
|
||||
jq_resize = $.resize = $.extend( $.resize, {} ),
|
||||
|
||||
timeout_id,
|
||||
|
||||
// Reused strings.
|
||||
str_setTimeout = 'setTimeout',
|
||||
str_resize = 'resize',
|
||||
str_data = str_resize + '-special-event',
|
||||
str_delay = 'delay',
|
||||
str_throttle = 'throttleWindow';
|
||||
|
||||
// Property: jQuery.resize.delay
|
||||
//
|
||||
// The numeric interval (in milliseconds) at which the resize event polling
|
||||
// loop executes. Defaults to 250.
|
||||
|
||||
jq_resize[ str_delay ] = 250;
|
||||
|
||||
// Property: jQuery.resize.throttleWindow
|
||||
//
|
||||
// Throttle the native window object resize event to fire no more than once
|
||||
// every <jQuery.resize.delay> milliseconds. Defaults to true.
|
||||
//
|
||||
// Because the window object has its own resize event, it doesn't need to be
|
||||
// provided by this plugin, and its execution can be left entirely up to the
|
||||
// browser. However, since certain browsers fire the resize event continuously
|
||||
// while others do not, enabling this will throttle the window resize event,
|
||||
// making event behavior consistent across all elements in all browsers.
|
||||
//
|
||||
// While setting this property to false will disable window object resize
|
||||
// event throttling, please note that this property must be changed before any
|
||||
// window object resize event callbacks are bound.
|
||||
|
||||
jq_resize[ str_throttle ] = true;
|
||||
|
||||
// Event: resize event
|
||||
//
|
||||
// Fired when an element's width or height changes. Because browsers only
|
||||
// provide this event for the window element, for other elements a polling
|
||||
// loop is initialized, running every <jQuery.resize.delay> milliseconds
|
||||
// to see if elements' dimensions have changed. You may bind with either
|
||||
// .resize( fn ) or .bind( "resize", fn ), and unbind with .unbind( "resize" ).
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// > jQuery('selector').bind( 'resize', function(e) {
|
||||
// > // element's width or height has changed!
|
||||
// > ...
|
||||
// > });
|
||||
//
|
||||
// Additional Notes:
|
||||
//
|
||||
// * The polling loop is not created until at least one callback is actually
|
||||
// bound to the 'resize' event, and this single polling loop is shared
|
||||
// across all elements.
|
||||
//
|
||||
// Double firing issue in jQuery 1.3.2:
|
||||
//
|
||||
// While this plugin works in jQuery 1.3.2, if an element's event callbacks
|
||||
// are manually triggered via .trigger( 'resize' ) or .resize() those
|
||||
// callbacks may double-fire, due to limitations in the jQuery 1.3.2 special
|
||||
// events system. This is not an issue when using jQuery 1.4+.
|
||||
//
|
||||
// > // While this works in jQuery 1.4+
|
||||
// > $(elem).css({ width: new_w, height: new_h }).resize();
|
||||
// >
|
||||
// > // In jQuery 1.3.2, you need to do this:
|
||||
// > var elem = $(elem);
|
||||
// > elem.css({ width: new_w, height: new_h });
|
||||
// > elem.data( 'resize-special-event', { width: elem.width(), height: elem.height() } );
|
||||
// > elem.resize();
|
||||
|
||||
$.event.special[ str_resize ] = {
|
||||
|
||||
// Called only when the first 'resize' event callback is bound per element.
|
||||
setup: function() {
|
||||
// Since window has its own native 'resize' event, return false so that
|
||||
// jQuery will bind the event using DOM methods. Since only 'window'
|
||||
// objects have a .setTimeout method, this should be a sufficient test.
|
||||
// Unless, of course, we're throttling the 'resize' event for window.
|
||||
if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
|
||||
|
||||
var elem = $(this);
|
||||
|
||||
// Add this element to the list of internal elements to monitor.
|
||||
elems = elems.add( elem );
|
||||
|
||||
// Initialize data store on the element.
|
||||
$.data( this, str_data, { w: elem.width(), h: elem.height() } );
|
||||
|
||||
// If this is the first element added, start the polling loop.
|
||||
if ( elems.length === 1 ) {
|
||||
loopy();
|
||||
}
|
||||
},
|
||||
|
||||
// Called only when the last 'resize' event callback is unbound per element.
|
||||
teardown: function() {
|
||||
// Since window has its own native 'resize' event, return false so that
|
||||
// jQuery will unbind the event using DOM methods. Since only 'window'
|
||||
// objects have a .setTimeout method, this should be a sufficient test.
|
||||
// Unless, of course, we're throttling the 'resize' event for window.
|
||||
if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
|
||||
|
||||
var elem = $(this);
|
||||
|
||||
// Remove this element from the list of internal elements to monitor.
|
||||
elems = elems.not( elem );
|
||||
|
||||
// Remove any data stored on the element.
|
||||
elem.removeData( str_data );
|
||||
|
||||
// If this is the last element removed, stop the polling loop.
|
||||
if ( !elems.length ) {
|
||||
clearTimeout( timeout_id );
|
||||
}
|
||||
},
|
||||
|
||||
// Called every time a 'resize' event callback is bound per element (new in
|
||||
// jQuery 1.4).
|
||||
add: function( handleObj ) {
|
||||
// Since window has its own native 'resize' event, return false so that
|
||||
// jQuery doesn't modify the event object. Unless, of course, we're
|
||||
// throttling the 'resize' event for window.
|
||||
if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
|
||||
|
||||
var old_handler;
|
||||
|
||||
// The new_handler function is executed every time the event is triggered.
|
||||
// This is used to update the internal element data store with the width
|
||||
// and height when the event is triggered manually, to avoid double-firing
|
||||
// of the event callback. See the "Double firing issue in jQuery 1.3.2"
|
||||
// comments above for more information.
|
||||
|
||||
function new_handler( e, w, h ) {
|
||||
var elem = $(this),
|
||||
data = $.data( this, str_data );
|
||||
|
||||
// If called from the polling loop, w and h will be passed in as
|
||||
// arguments. If called manually, via .trigger( 'resize' ) or .resize(),
|
||||
// those values will need to be computed.
|
||||
data.w = w !== undefined ? w : elem.width();
|
||||
data.h = h !== undefined ? h : elem.height();
|
||||
|
||||
old_handler.apply( this, arguments );
|
||||
};
|
||||
|
||||
// This may seem a little complicated, but it normalizes the special event
|
||||
// .add method between jQuery 1.4/1.4.1 and 1.4.2+
|
||||
if ( $.isFunction( handleObj ) ) {
|
||||
// 1.4, 1.4.1
|
||||
old_handler = handleObj;
|
||||
return new_handler;
|
||||
} else {
|
||||
// 1.4.2+
|
||||
old_handler = handleObj.handler;
|
||||
handleObj.handler = new_handler;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function loopy() {
|
||||
|
||||
// Start the polling loop, asynchronously.
|
||||
timeout_id = window[ str_setTimeout ](function(){
|
||||
|
||||
// Iterate over all elements to which the 'resize' event is bound.
|
||||
elems.each(function(){
|
||||
var elem = $(this),
|
||||
width = elem.width(),
|
||||
height = elem.height(),
|
||||
data = $.data( this, str_data );
|
||||
|
||||
// If element size has changed since the last time, update the element
|
||||
// data store and trigger the 'resize' event.
|
||||
if ( width !== data.w || height !== data.h ) {
|
||||
elem.trigger( str_resize, [ data.w = width, data.h = height ] );
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Loop.
|
||||
loopy();
|
||||
|
||||
}, jq_resize[ str_delay ] );
|
||||
|
||||
};
|
||||
|
||||
})(jQuery,this);
|
Loading…
Reference in a new issue