From 2eb0c89f311b9973190b52820d16c1eb2b2a7e8d Mon Sep 17 00:00:00 2001
From: vrubezhny <vrubezhny@exadel.com>
Date: Fri, 3 Oct 2014 00:03:34 +0400
Subject: [PATCH] Bug 444545 - [validation] Ability to ignore custom html tag

Now it's able to ignore html element names from validation using comma-separated name patterns, that can be
specified on Validation Preference page, or set by a quick fix.

Signed-off-by: vrubezhny <vrubezhny@exadel.com>
---
 .../preferences/HTMLCorePreferenceInitializer.java |   6 +-
 .../preferences/HTMLCorePreferenceNames.java       |  18 +-
 .../core/internal/validate/SyntaxValidator.java    |  73 ++++++-
 bundles/org.eclipse.wst.html.ui/plugin.xml         |   4 +
 .../wst/html/ui/internal/HTMLUIMessages.java       |  11 +-
 .../ui/internal/HTMLUIPluginResources.properties   |  10 +-
 .../ui/HTMLValidationPreferencePage.java           | 185 ++++++++++++++---
 .../HTMLSyntaxValidationQuickFixProcessor.java     | 228 +++++++++++++++++++++
 .../IgnoreAttributeNameCompletionProposal.java     |   2 +-
 .../IgnoreElementNameCompletionProposal.java       | 217 ++++++++++++++++++++
 10 files changed, 721 insertions(+), 33 deletions(-)
 create mode 100644 bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/HTMLSyntaxValidationQuickFixProcessor.java
 create mode 100644 bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreElementNameCompletionProposal.java

diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceInitializer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceInitializer.java
index f3a4b14..a04daf8 100644
--- a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceInitializer.java
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceInitializer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2013 IBM Corporation and others.
+ * Copyright (c) 2005, 2014 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -72,6 +72,10 @@ public class HTMLCorePreferenceInitializer extends AbstractPreferenceInitializer
 	 * @param node the Eclipse preference node
 	 */
 	private void initializeValidationPreferences(IEclipsePreferences node) {
+		// Ignored Element names
+		node.putBoolean(HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES, HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES_DEFAULT);
+		node.put(HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE, HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE_DEFAULT);
+		
 		// Ignored Attribute names
 		node.putBoolean(HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES, HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES_DEFAULT);
 		node.put(HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE, HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE_DEFAULT);
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceNames.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceNames.java
index 2b9e70e..83d9135 100644
--- a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceNames.java
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceNames.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2013 IBM Corporation and others.
+ * Copyright (c) 2005, 2014 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -239,6 +239,20 @@ public class HTMLCorePreferenceNames {
 	public static final int UPPER = 2;
 	
 	/**
+	 * Default value for the preference #IGNORE_ELEMENT_NAMES
+	 * 
+	 * @see #IGNORE_ELEMENT_NAMES
+	 */
+	public static final boolean IGNORE_ELEMENT_NAMES_DEFAULT = false;
+
+	/**
+	 * Default value for the preference #ELEMENT_NAMES_TO_IGNORE
+	 * 
+	 * @see #ELEMENT_NAMES_TO_IGNORE
+	 */
+	public static final String ELEMENT_NAMES_TO_IGNORE_DEFAULT = ""; //$NON-NLS-1$
+	
+	/**
 	 * Default value for the preference #IGNORE_ATTRIBUTE_NAMES
 	 * 
 	 * @see #IGNORE_ATTRIBUTE_NAMES
@@ -253,6 +267,8 @@ public class HTMLCorePreferenceNames {
 	public static final String ATTRIBUTE_NAMES_TO_IGNORE_DEFAULT = ""; //$NON-NLS-1$
 	
 	public static final String USE_PROJECT_SETTINGS = "use-project-settings";//$NON-NLS-1$
+	public static final String IGNORE_ELEMENT_NAMES = "ignoreElementNames";//$NON-NLS-1$
+	public static final String ELEMENT_NAMES_TO_IGNORE = "elementNamesToIgnore";//$NON-NLS-1$
 	public static final String IGNORE_ATTRIBUTE_NAMES = "ignoreAttrNames";//$NON-NLS-1$
 	public static final String ATTRIBUTE_NAMES_TO_IGNORE = "attrNamesToIgnore";//$NON-NLS-1$
 	
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java
index 31ea9c0..adc1f1d 100644
--- a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * Copyright (c) 2004, 2014 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,12 +10,27 @@
  *******************************************************************************/
 package org.eclipse.wst.html.core.internal.validate;
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
-
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
 import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
 import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration;
 import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
 import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
 import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
 import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
 import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
@@ -36,7 +51,8 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
 class SyntaxValidator extends PrimeValidator implements ErrorState {
-
+	private IPreferencesService fPreferenceService;
+	private static Map fIgnorePatterns = new HashMap(); // A storage for ignore patterns (instances of StringMatcher)
 
 	static private boolean isValidRegion(ITextRegion rgn) {
 		String type = rgn.getType();
@@ -65,6 +81,7 @@ class SyntaxValidator extends PrimeValidator implements ErrorState {
 
 	public SyntaxValidator() {
 		super();
+		fPreferenceService = Platform.getPreferencesService();
 	}
 
 	public boolean isAdapterForType(Object type) {
@@ -306,6 +323,9 @@ class SyntaxValidator extends PrimeValidator implements ErrorState {
 				reportCorruptedEndTagError(info);
 			}
 			else {
+				if (!shouldValidateElementName(info.target))
+					return;
+				
 				Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG_NAME);
 				report(UNDEFINED_NAME_ERROR, errorSeg, info.target);
 			}
@@ -320,6 +340,53 @@ class SyntaxValidator extends PrimeValidator implements ErrorState {
 		}
 	}
 
+	private boolean shouldValidateElementName(Element target) {
+		Object adapter = (target instanceof IAdaptable ? ((IAdaptable)target).getAdapter(IResource.class) : null);
+		IProject project = (adapter instanceof IResource ? ((IResource)adapter).getProject() : null);
+		
+		Iterator excludedElements = getExcludedElementNames(project).iterator();
+		while (excludedElements.hasNext()) {
+			String excluded = (String)excludedElements.next();
+			StringMatcher strMatcher = (StringMatcher)fIgnorePatterns.get(excluded);
+			if (strMatcher == null) {
+				strMatcher = new StringMatcher(excluded);
+				fIgnorePatterns.put(excluded, strMatcher);
+			}
+			if (strMatcher.match(target.getNodeName()))
+				return false;
+		}
+		return true;
+	}
+
+	private Set getExcludedElementNames(IProject project) {
+		IScopeContext[] fLookupOrder = new IScopeContext[] {new InstanceScope(), new DefaultScope()};
+		if (project != null) {
+			ProjectScope projectScope = new ProjectScope(project);
+			if(projectScope.getNode(HTMLCorePlugin.getDefault().getBundle().getSymbolicName()).getBoolean(HTMLCorePreferenceNames.USE_PROJECT_SETTINGS, false))
+				fLookupOrder = new IScopeContext[] {projectScope, new InstanceScope(), new DefaultScope()};
+		}
+
+		Set result = new HashSet();
+		if (fPreferenceService.getBoolean(HTMLCorePlugin.getDefault().getBundle().getSymbolicName(), 
+				HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES, HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES_DEFAULT, 
+				fLookupOrder)) {
+			String ignoreList = fPreferenceService.getString(HTMLCorePlugin.getDefault().getBundle().getSymbolicName(), 
+					HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE, HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE_DEFAULT, 
+					fLookupOrder);
+
+			if (ignoreList.trim().isEmpty())
+				return result;
+
+			String[] names = ignoreList.split(","); //$NON-NLS-1$
+			for (int i = 0; names != null && i < names.length; i++) {
+				String name = names[i] == null ? null : names[i].trim();
+				if (name != null && !name.isEmpty()) 
+					result.add(name.toLowerCase());
+			}
+		}
+		return result; 
+	}
+	
 	/* perform validation tag case only for XHTML document */
 	private void validateTagCase(ElementInfo info) {
 		String declared = info.decl.getElementName();
diff --git a/bundles/org.eclipse.wst.html.ui/plugin.xml b/bundles/org.eclipse.wst.html.ui/plugin.xml
index 8bf535d..2509e46 100644
--- a/bundles/org.eclipse.wst.html.ui/plugin.xml
+++ b/bundles/org.eclipse.wst.html.ui/plugin.xml
@@ -54,6 +54,10 @@
 			class="org.eclipse.wst.html.ui.internal.text.correction.HTMLAttributeValidationQuickFixProcessor"
 			target="org.eclipse.wst.html.HTML_DEFAULT" />
 		<provisionalConfiguration
+			type="org.eclipse.jface.text.quickassist.IQuickAssistProcessor"
+			class="org.eclipse.wst.html.ui.internal.text.correction.HTMLSyntaxValidationQuickFixProcessor"
+			target="org.eclipse.wst.html.HTML_DEFAULT" />
+		<provisionalConfiguration
 			type="autoeditstrategy"
 			class="org.eclipse.wst.html.ui.internal.autoedit.StructuredAutoEditStrategyHTML"
 			target="org.eclipse.wst.html.HTML_DEFAULT, org.eclipse.wst.html.HTML_DECLARATION" />
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIMessages.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIMessages.java
index 1538506..275cdfb 100644
--- a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIMessages.java
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIMessages.java
@@ -1,5 +1,5 @@
 /**********************************************************************
- * Copyright (c) 2005, 2013 IBM Corporation and others. All rights reserved.   This
+ * Copyright (c) 2005, 2014 IBM Corporation and others. All rights reserved.   This
  * program and the accompanying materials are made available under the terms of
  * the Eclipse Public License v1.0 which accompanies this distribution, and is
  * available at http://www.eclipse.org/legal/epl-v10.html
@@ -210,6 +210,15 @@ public class HTMLUIMessages extends NLS {
 	public static String Hyperlink_line;
 	public static String Open;
 	
+	// Ignore Element Name Patterns
+	public static String IgnoreElementNames;
+	public static String IgnoreElementNamesPattern;
+	public static String BadIgnoreElementNamesPattern;
+	public static String DoNotValidateElement;
+	public static String DoNotValidateAllElements;
+	public static String DoNotValidateElementAddInfo;
+	public static String DoNotValidateAllElementsAddInfo;
+
 	// Ignore Attribute Name Patterns
 	public static String IgnoreAttributeNames;
 	public static String IgnoreAttributeNamesPattern;
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPluginResources.properties b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPluginResources.properties
index b1e3b78..bdf842b 100644
--- a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPluginResources.properties
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPluginResources.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2004, 2013 IBM Corporation and others.
+# Copyright (c) 2004, 2014 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -182,6 +182,14 @@ HTMLValidationPreferencePage_37=Missing attribute equals sign character:
 Hyperlink_line={0}={1} : line {2}
 Open=Open ''{0}''
 
+IgnoreElementNames=Ignore specified element names in validation
+IgnoreElementNamesPattern=Specify comma-separated patterns for element names to be ignored:
+BadIgnoreElementNamesPattern=''{0}'' is not a valid element names pattern
+DoNotValidateElement=Ignore ''{0}'' element in validation
+DoNotValidateAllElements=Ignore all ''{0}'' elements in validation
+DoNotValidateElementAddInfo=Adds the name of element to the list of ignored elements for HTML Syntax Validator<br>You may edit the list of ignored elements at <b>Web&#x2192;HTML Files&#x2192;Validation</b> Preference Page
+DoNotValidateAllElementsAddInfo=Adds the pattern based on the element name to the list of ignored elements for HTML Syntax Validator<br>You may edit the list of ignored elements at <b>Web&#x2192;HTML Files&#x2192;Validation</b> Preference Page
+
 IgnoreAttributeNames=Ignore specified attribute names in validation
 IgnoreAttributeNamesPattern=Specify comma-separated patterns for attribute names to be ignored:
 BadIgnoreAttributeNamesPattern=''{0}'' is not a valid attribute names pattern
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLValidationPreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLValidationPreferencePage.java
index b707d1d..15d6d41 100644
--- a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLValidationPreferencePage.java
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLValidationPreferencePage.java
@@ -17,6 +17,7 @@ import org.eclipse.core.runtime.preferences.IPreferencesService;
 import org.eclipse.core.runtime.preferences.IScopeContext;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.jface.layout.PixelConverter;
+import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ModifyEvent;
@@ -39,8 +40,10 @@ import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
 import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
 import org.eclipse.wst.html.ui.internal.Logger;
 import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
 import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractValidationSettingsPage;
 import org.eclipse.wst.sse.ui.internal.preferences.ui.ScrolledPageContent;
+import org.eclipse.wst.sse.ui.internal.provisional.preferences.CommonEditorPreferenceNames;
 import org.osgi.service.prefs.BackingStoreException;
 
 public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage {
@@ -131,19 +134,55 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 	}
 	
 	private PixelConverter fPixelConverter;
+	private Button fIgnoreElementNames;
+	private Label fIgnoredElementNamesLabel;
+	private Text fIgnoredElementNames;
 	private Button fIgnoreAttributeNames;
 	private Label fIgnoredAttributeNamesLabel;
 	private Text fIgnoredAttributeNames;
 	private IPreferencesService fPreferencesService = null;
 	
-	private boolean fUseOriginOverrides = false;
+	private boolean fUseElementsOriginOverrides = false;
+	private boolean fIgnoreElementNamesOriginOverride = HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES_DEFAULT;
+	private String  fIgnoredElementNamesOriginOverride = HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE_DEFAULT;
+
+	private boolean fUseAttributesOriginOverrides = false;
 	private boolean fIgnoreAttributeNamesOriginOverride = HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES_DEFAULT;
 	private String  fIgnoredAttributeNamesOriginOverride = HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE_DEFAULT;
 
+	public void overrideIgnoredElementsOriginValues(boolean enableIgnore, String elementNames) {
+		fIgnoreElementNamesOriginOverride = enableIgnore;
+		fIgnoredElementNamesOriginOverride = elementNames;
+		fUseElementsOriginOverrides = true;
+		
+		if (fIgnoreElementNames != null) {
+			BooleanData data = (BooleanData)fIgnoreElementNames.getData();
+			if (data != null)
+				data.originalValue = fIgnoreElementNamesOriginOverride;
+		}
+		if (fIgnoredElementNames != null) {
+			TextData data = (TextData)fIgnoredElementNames.getData();
+			if (data != null)
+				data.originalValue = fIgnoredElementNamesOriginOverride;
+		}
+	}
+
+	/**
+	 * Overrides the origin values for Ignored Attribute Names
+	 * 
+	 * @deprecated Use overrideIgnoredAttributesOriginValues(boolean, String)
+	 * 
+	 * @param enableIgnore
+	 * @param attributeNames
+	 */
 	public void overrideOriginValues(boolean enableIgnore, String attributeNames) {
+		this.overrideIgnoredAttributesOriginValues(enableIgnore, attributeNames);
+	}
+	
+	public void overrideIgnoredAttributesOriginValues(boolean enableIgnore, String attributeNames) {
 		fIgnoreAttributeNamesOriginOverride = enableIgnore;
 		fIgnoredAttributeNamesOriginOverride = attributeNames;
-		fUseOriginOverrides = true;
+		fUseAttributesOriginOverrides = true;
 		
 		if (fIgnoreAttributeNames != null) {
 			BooleanData data = (BooleanData)fIgnoreAttributeNames.getData();
@@ -156,7 +195,7 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 				data.originalValue = fIgnoredAttributeNamesOriginOverride;
 		}
 	}
-	
+
 	protected Control createCommonContents(Composite parent) {
 		final Composite page = new Composite(parent, SWT.NULL);
 		
@@ -188,8 +227,61 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 		layout.marginWidth= 0;
 		composite.setLayout(layout);
 		
+		// Ignored Element Names Pattern
+		BooleanData ignoreData = new BooleanData(HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES);
+		fIgnoreElementNames = new Button(composite, SWT.CHECK);
+		fIgnoreElementNames.setData(ignoreData);
+		fIgnoreElementNames.setFont(page.getFont());
+		fIgnoreElementNames.setText(HTMLUIMessages.IgnoreElementNames);
+		fIgnoreElementNames.setEnabled(true);
+		
+		boolean ignoreElementNamesIsSelected = fPreferencesService.getBoolean(getPreferenceNodeQualifier(), 
+				ignoreData.getKey(), HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES_DEFAULT, createPreferenceScopes());
+		ignoreData.setValue(ignoreElementNamesIsSelected);
+		ignoreData.originalValue = fUseElementsOriginOverrides ? fIgnoreElementNamesOriginOverride : ignoreElementNamesIsSelected;
+		
+		fIgnoreElementNames.setSelection(ignoreData.getValue());
+		fIgnoreElementNames.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				controlChanged(e.widget);
+			}
+			public void widgetSelected(SelectionEvent e) {
+				controlChanged(e.widget);
+			}
+		});
+		fIgnoreElementNames.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
+		
+		fIgnoredElementNamesLabel = new Label(composite, SWT.LEFT | SWT.WRAP);
+		fIgnoredElementNamesLabel.setFont(composite.getFont());
+		fIgnoredElementNamesLabel.setEnabled(ignoreData.getValue());
+		fIgnoredElementNamesLabel.setText(HTMLUIMessages.IgnoreElementNamesPattern);
+		fIgnoredElementNamesLabel.setLayoutData(new GridData(SWT.FILL, SWT.END, true, false, 3, 1));
+		setHorizontalIndent(fIgnoredElementNamesLabel, 20);
+
+		TextData data = new TextData(HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE);
+		fIgnoredElementNames = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		fIgnoredElementNames.setData(data);
+		fIgnoredElementNames.setTextLimit(500);
+		fIgnoredElementNames.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 3, 1));
+		setHorizontalIndent(fIgnoredElementNames, 20);
+		setWidthHint(fIgnoredElementNames, convertWidthInCharsToPixels(65));
+		String ignoredElementNames = fPreferencesService.getString(getPreferenceNodeQualifier(), data.getKey(), HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE_DEFAULT, createPreferenceScopes());
+		data.setValue(ignoredElementNames);
+		data.originalValue = fUseElementsOriginOverrides ? fIgnoredElementNamesOriginOverride : ignoredElementNames;
+		fIgnoredElementNames.setText(data.getValue());
+		
+		fIgnoredElementNames.addModifyListener(new ModifyListener() {
+			
+			public void modifyText(ModifyEvent e) {
+				if (verifyIgnoredNames(fIgnoredElementNames.getText().trim())) {
+					controlChanged(e.widget);
+				}
+			}
+		});
+		controlChanged(fIgnoreElementNames);
+
 		// Ignored Attribute Names Pattern
-		BooleanData ignoreData = new BooleanData(HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES);
+		ignoreData = new BooleanData(HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES);
 		fIgnoreAttributeNames = new Button(composite, SWT.CHECK);
 		fIgnoreAttributeNames.setData(ignoreData);
 		fIgnoreAttributeNames.setFont(page.getFont());
@@ -199,7 +291,7 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 		boolean ignoreAttributeNamesIsSelected = fPreferencesService.getBoolean(getPreferenceNodeQualifier(), 
 				ignoreData.getKey(), HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES_DEFAULT, createPreferenceScopes());
 		ignoreData.setValue(ignoreAttributeNamesIsSelected);
-		ignoreData.originalValue = fUseOriginOverrides ? fIgnoreAttributeNamesOriginOverride : ignoreAttributeNamesIsSelected;
+		ignoreData.originalValue = fUseAttributesOriginOverrides ? fIgnoreAttributeNamesOriginOverride : ignoreAttributeNamesIsSelected;
 		
 		fIgnoreAttributeNames.setSelection(ignoreData.getValue());
 		fIgnoreAttributeNames.addSelectionListener(new SelectionListener() {
@@ -219,7 +311,7 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 		fIgnoredAttributeNamesLabel.setLayoutData(new GridData(SWT.FILL, SWT.END, true, false, 3, 1));
 		setHorizontalIndent(fIgnoredAttributeNamesLabel, 20);
 
-		TextData data = new TextData(HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE);
+		data = new TextData(HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE);
 		fIgnoredAttributeNames = new Text(composite, SWT.SINGLE | SWT.BORDER);
 		fIgnoredAttributeNames.setData(data);
 		fIgnoredAttributeNames.setTextLimit(500);
@@ -228,13 +320,13 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 		setWidthHint(fIgnoredAttributeNames, convertWidthInCharsToPixels(65));
 		String ignoredAttributeNames = fPreferencesService.getString(getPreferenceNodeQualifier(), data.getKey(), HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE_DEFAULT, createPreferenceScopes());
 		data.setValue(ignoredAttributeNames);
-		data.originalValue = fUseOriginOverrides ? fIgnoredAttributeNamesOriginOverride : ignoredAttributeNames;
+		data.originalValue = fUseAttributesOriginOverrides ? fIgnoredAttributeNamesOriginOverride : ignoredAttributeNames;
 		fIgnoredAttributeNames.setText(data.getValue());
 		
 		fIgnoredAttributeNames.addModifyListener(new ModifyListener() {
 			
 			public void modifyText(ModifyEvent e) {
-				if (verifyIgnoredAttributeNames()) {
+				if (verifyIgnoredNames(fIgnoredAttributeNames.getText().trim())) {
 					controlChanged(e.widget);
 				}
 			}
@@ -470,12 +562,11 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 		}
 	}
 	
-	private boolean verifyIgnoredAttributeNames() {
-		final String text = fIgnoredAttributeNames.getText().trim();
-		if (text.length() == 0)
+	private boolean verifyIgnoredNames(String value) {
+		if (value.length() == 0)
 			return true;
 
-		String[] names = text.split(","); //$NON-NLS-1$
+		String[] names = value.split(","); //$NON-NLS-1$
 		boolean valid = true;
 		for (int i = 0; names != null && i < names.length; i++) {
 			String name = names[i] == null ? null : names[i].trim();
@@ -490,7 +581,7 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 		}
 		
 		if (!valid) {
-			setErrorMessage(NLS.bind(HTMLUIMessages.BadIgnoreAttributeNamesPattern, text));
+			setErrorMessage(NLS.bind(HTMLUIMessages.BadIgnoreAttributeNamesPattern, value));
 			setValid(false);
 		} else {
 			setErrorMessage(null);
@@ -508,10 +599,18 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 			BooleanData data = (BooleanData) widget.getData();
 			if (data != null) {
 				data.setValue(((Button)widget).getSelection());
-				fIgnoredAttributeNamesLabel.setEnabled(data.getValue());
-				fIgnoredAttributeNames.setEnabled(data.getValue());
-				if (data.getValue()) {
-					fIgnoredAttributeNames.setFocus();
+				if (fIgnoreElementNames == widget) {
+					fIgnoredElementNamesLabel.setEnabled(data.getValue());
+					fIgnoredElementNames.setEnabled(data.getValue());
+					if (data.getValue()) {
+						fIgnoredElementNames.setFocus();
+					}
+				} else if (fIgnoreAttributeNames == widget) {
+					fIgnoredAttributeNamesLabel.setEnabled(data.getValue());
+					fIgnoredAttributeNames.setEnabled(data.getValue());
+					if (data.getValue()) {
+						fIgnoredAttributeNames.setFocus();
+					}
 				}
 			}
 		} else {
@@ -524,11 +623,19 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 	 * causing the full validation to be requested.
 	 */
 	protected boolean shouldRevalidateOnSettingsChange() {
-		TextData data = (TextData)fIgnoredAttributeNames.getData();
+		TextData data = (TextData)fIgnoredElementNames.getData();
+		if (data.isChanged())
+			return true;
+		
+		BooleanData ignoreData = (BooleanData)fIgnoreElementNames.getData();
+		if (ignoreData.isChanged())
+			return true;
+		
+		data = (TextData)fIgnoredAttributeNames.getData();
 		if (data.isChanged())
 			return true;
 		
-		BooleanData ignoreData = (BooleanData)fIgnoreAttributeNames.getData();
+		ignoreData = (BooleanData)fIgnoreAttributeNames.getData();
 		if (ignoreData.isChanged())
 			return true;
 		
@@ -542,11 +649,19 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 	protected void storeValues() {
 		IScopeContext[] contexts = createPreferenceScopes();
 
-		BooleanData ignoreData = (BooleanData)fIgnoreAttributeNames.getData();
+		BooleanData ignoreData = (BooleanData)fIgnoreElementNames.getData();
 		contexts[0].getNode(getPreferenceNodeQualifier()).putBoolean(ignoreData.getKey(), ignoreData.getValue()); 
 		ignoreData.originalValue = ignoreData.getValue();
 
-		TextData data = (TextData)fIgnoredAttributeNames.getData();
+		TextData data = (TextData)fIgnoredElementNames.getData();
+		contexts[0].getNode(getPreferenceNodeQualifier()).put(data.getKey(), data.getValue()); 
+		data.originalValue = data.getValue();
+
+		ignoreData = (BooleanData)fIgnoreAttributeNames.getData();
+		contexts[0].getNode(getPreferenceNodeQualifier()).putBoolean(ignoreData.getKey(), ignoreData.getValue()); 
+		ignoreData.originalValue = ignoreData.getValue();
+
+		data = (TextData)fIgnoredAttributeNames.getData();
 		contexts[0].getNode(getPreferenceNodeQualifier()).put(data.getKey(), data.getValue()); 
 		data.originalValue = data.getValue();
 
@@ -559,6 +674,15 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 		}
 
 		super.storeValues();
+		
+		forceReconciling();
+	}
+	
+	private void forceReconciling() {
+		IPreferenceStore store = SSEUIPlugin.getDefault().getPreferenceStore();
+		boolean value = store.getBoolean(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS);
+		store.setValue(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS, !value);
+		store.setValue(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS, value);
 	}
 	
 	/*
@@ -566,19 +690,30 @@ public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage
 	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
 	 */
 	protected void performDefaults() {
-		resetIgnoreAttributeNamesPattern();
+		resetIgnoreNamesPatterns();
 		resetSeverities();
 		super.performDefaults();
 	}
 	
-	protected void resetIgnoreAttributeNamesPattern() {
+	protected void resetIgnoreNamesPatterns() {
 		IEclipsePreferences defaultContext = new DefaultScope().getNode(getPreferenceNodeQualifier());
-		BooleanData ignoreData = (BooleanData)fIgnoreAttributeNames.getData();
+
+		BooleanData ignoreData = (BooleanData)fIgnoreElementNames.getData();
+		boolean ignoreElementNames = defaultContext.getBoolean(ignoreData.getKey(), HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES_DEFAULT);
+		ignoreData.setValue(ignoreElementNames);
+		fIgnoreElementNames.setSelection(ignoreData.getValue());
+
+		TextData data = (TextData)fIgnoredElementNames.getData();
+		String ignoredElementNames = defaultContext.get(data.getKey(), HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE_DEFAULT);
+		data.setValue(ignoredElementNames);
+		fIgnoredElementNames.setText(data.getValue());
+
+		ignoreData = (BooleanData)fIgnoreAttributeNames.getData();
 		boolean ignoreAttributeNames = defaultContext.getBoolean(ignoreData.getKey(), HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES_DEFAULT);
 		ignoreData.setValue(ignoreAttributeNames);
 		fIgnoreAttributeNames.setSelection(ignoreData.getValue());
 
-		TextData data = (TextData)fIgnoredAttributeNames.getData();
+		data = (TextData)fIgnoredAttributeNames.getData();
 		String ignoredAttributeNames = defaultContext.get(data.getKey(), HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE_DEFAULT);
 		data.setValue(ignoredAttributeNames);
 		fIgnoredAttributeNames.setText(data.getValue());
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/HTMLSyntaxValidationQuickFixProcessor.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/HTMLSyntaxValidationQuickFixProcessor.java
new file mode 100644
index 0000000..8519da1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/HTMLSyntaxValidationQuickFixProcessor.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text.correction;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
+import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelExtension2;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+import org.eclipse.wst.html.core.internal.HTMLCoreMessages;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.validate.StringMatcher;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Element;
+
+public class HTMLSyntaxValidationQuickFixProcessor implements IQuickAssistProcessor {
+
+	private StringMatcher UNKNOWN_ELEMENT_NAME_MATCHER;
+	private IPreferencesService fPreferenceService;
+
+	public HTMLSyntaxValidationQuickFixProcessor() {
+		UNKNOWN_ELEMENT_NAME_MATCHER = new StringMatcher(NLS.bind(HTMLCoreMessages.Unknown_tag___0____ERROR_, "*")); //$NON-NLS-1$
+		fPreferenceService = Platform.getPreferencesService();
+	}
+	
+	/*
+	 * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#getErrorMessage()
+	 */
+	public String getErrorMessage() {
+		return null;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canFix(org.eclipse.jface.text.source.Annotation)
+	 */
+	public boolean canFix(Annotation annotation) {
+		boolean result = false;
+
+		String text = null;
+		if (annotation instanceof TemporaryAnnotation) {
+			TemporaryAnnotation tempAnnotation = (TemporaryAnnotation) annotation;
+			int problemID = tempAnnotation.getProblemID();
+			text = tempAnnotation.getText();
+
+			if (problemID == 0 && text != null)
+				result = true;
+		} else if (annotation instanceof MarkerAnnotation) {
+			MarkerAnnotation markerAnnotation = (MarkerAnnotation) annotation;
+			text = markerAnnotation.getText();
+			IMarker marker = markerAnnotation.getMarker();
+			IResource resource = marker == null ? null : marker.getResource();
+			if (resource != null && resource.exists() && resource.isAccessible() && text != null) {
+				result = true;
+			}
+		}
+		
+		result = (result && UNKNOWN_ELEMENT_NAME_MATCHER.match(text));
+
+		return result;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#canAssist(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext)
+	 */
+	public boolean canAssist(IQuickAssistInvocationContext invocationContext) {
+		return true;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.quickassist.IQuickAssistProcessor#computeQuickAssistProposals(org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext)
+	 */
+	public ICompletionProposal[] computeQuickAssistProposals(
+			IQuickAssistInvocationContext invocationContext) {
+		ISourceViewer viewer = invocationContext.getSourceViewer();
+		int documentOffset = invocationContext.getOffset();
+		int length = viewer != null ? viewer.getSelectedRange().y : 0;
+
+		IAnnotationModel model = viewer.getAnnotationModel();
+		if (model == null)
+			return null;
+
+		List proposals = new ArrayList();
+		if (model instanceof IAnnotationModelExtension2) {
+			Iterator iter = ((IAnnotationModelExtension2) model).getAnnotationIterator(documentOffset, length, true, true);
+			while (iter.hasNext()) {
+				Annotation anno = (Annotation) iter.next();
+				if (canFix(anno)) {
+					int offset = -1;
+					
+					if (anno instanceof TemporaryAnnotation) {
+						offset = ((TemporaryAnnotation)anno).getPosition().getOffset();
+					} else if (anno instanceof MarkerAnnotation) {
+						offset = ((MarkerAnnotation)anno).getMarker().getAttribute(IMarker.CHAR_START, -1);
+					}
+					if (offset == -1)
+						continue;
+
+					IDOMNode node = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+					if (!(node instanceof Element))
+						continue;
+
+					Object adapter = (node instanceof IAdaptable ? ((IAdaptable)node).getAdapter(IResource.class) : null);
+					IProject project = (adapter instanceof IResource ? ((IResource)adapter).getProject() : null);
+
+					IScopeContext[] fLookupOrder = new IScopeContext[] {new InstanceScope(), new DefaultScope()};
+					if (project != null) {
+						ProjectScope projectScope = new ProjectScope(project);
+						if(projectScope.getNode(getPreferenceNodeQualifier())
+								.getBoolean(getProjectSettingsKey(), false))
+							fLookupOrder = new IScopeContext[] {projectScope, new InstanceScope(), new DefaultScope()};
+					}
+					
+					boolean ignore = fPreferenceService.getBoolean(
+							getPreferenceNodeQualifier(), HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES, 
+							HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES_DEFAULT, fLookupOrder);
+
+					String ignoreList = fPreferenceService.getString(
+							getPreferenceNodeQualifier(), HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE, 
+							HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE_DEFAULT, fLookupOrder);
+
+					Set result = new HashSet();
+					if (ignoreList.trim().length() > 0) {
+						String[] names = ignoreList.split(","); //$NON-NLS-1$
+						for (int i = 0; names != null && i < names.length; i++) {
+							String name = names[i] == null ? null : names[i].trim();
+							if (name != null && name.length() > 0) 
+								result.add(name.toLowerCase());
+						}
+					}
+					
+					String name = getElementName(node, offset);
+					if (name == null) continue;
+					
+					// If ignore == false. then show a quick fix anyway (due to allow to turn 'ignore' option on)
+					if (!ignore || shouldShowQuickFix(result, name.toLowerCase())) {
+						IgnoreElementNameCompletionProposal p = new IgnoreElementNameCompletionProposal(
+								name.toLowerCase(), offset, NLS.bind(HTMLUIMessages.DoNotValidateElement, name), 
+								HTMLUIMessages.DoNotValidateElementAddInfo, node);
+						if (!proposals.contains(p))
+							proposals.add(p);  
+					}
+					
+					int dashIndex = name.indexOf('-');
+					while (dashIndex != -1) {
+						StringBuffer namePattern = new StringBuffer(name.substring(0, dashIndex + 1)).append('*');
+						
+						// Do not continue creating proposals for the rest of patterns if 
+						// a more common pattern is already created
+						if (ignore && result.contains(namePattern.toString().toLowerCase()))
+							break;
+						
+						IgnoreElementNameCompletionProposal p = new IgnoreElementNameCompletionProposal(
+								namePattern.toString().toLowerCase(), offset, NLS.bind(HTMLUIMessages.DoNotValidateAllElements, namePattern.toString()), 
+								HTMLUIMessages.DoNotValidateAllElementsAddInfo, node); 
+						if (!proposals.contains(p))
+							proposals.add(p);  
+
+						dashIndex = name.indexOf('-', dashIndex + 1);
+					}
+				}
+			}
+		}
+
+		if (proposals.isEmpty())
+			return null;
+
+		return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+
+	}
+
+	private String getElementName(IDOMNode node, int offset) {
+		return node.getNodeName();
+	}
+	
+	private boolean shouldShowQuickFix(Set lcIgnoredPatterns, String attrName) {
+		// Check the attribute name absence in ignore list
+		String [] lcPatterns = (String[])lcIgnoredPatterns.toArray(new String[0]);
+		for (int i = 0; i < lcPatterns.length; i++) {
+			StringMatcher strMatcher = new StringMatcher(lcPatterns[i]);
+			if (strMatcher.match(attrName.toLowerCase())) {
+				return false; // The attribute name is already ignored, no need to show a quickfix
+			}
+		}
+
+		// The attribute name is not ignored yet, need to show a quickfix
+		return true;
+	}
+	
+	private String getPreferenceNodeQualifier() {
+		return HTMLCorePlugin.getDefault().getBundle().getSymbolicName();
+	}
+
+	private String getProjectSettingsKey() {
+		return HTMLCorePreferenceNames.USE_PROJECT_SETTINGS;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreAttributeNameCompletionProposal.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreAttributeNameCompletionProposal.java
index f43e9fe..605d509 100644
--- a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreAttributeNameCompletionProposal.java
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreAttributeNameCompletionProposal.java
@@ -117,7 +117,7 @@ public class IgnoreAttributeNameCompletionProposal implements ICompletionProposa
 		if (dialog != null) {
 			Object page = dialog.getSelectedPage();
 			if (page instanceof HTMLValidationPreferencePage) {
-				((HTMLValidationPreferencePage)page).overrideOriginValues(originalEnableIgnore, originalAttributeNames);
+				((HTMLValidationPreferencePage)page).overrideIgnoredAttributesOriginValues(originalEnableIgnore, originalAttributeNames);
 			}
 			result = dialog.open();
 		}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreElementNameCompletionProposal.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreElementNameCompletionProposal.java
new file mode 100644
index 0000000..0b19420
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/correction/IgnoreElementNameCompletionProposal.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text.correction;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.Logger;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImageHelper;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImages;
+import org.eclipse.wst.html.ui.internal.preferences.ui.HTMLValidationPreferencePage;
+import org.osgi.service.prefs.BackingStoreException;
+import org.w3c.dom.Node;
+
+public class IgnoreElementNameCompletionProposal implements ICompletionProposal {
+	/** The string to be added to the Ignored HTML Elements list. */
+	private String fPattern;
+	/** The target node */
+	private Node fTarget;
+	/** The string to be displayed in the completion proposal popup. */
+	private String fDisplayString;
+	/** The replacement offset. */
+	private int fReplacementOffset;
+	/** The context information of this proposal. */
+	private IContextInformation fContextInformation;
+	/** The additional info of this proposal. */
+	private String fAdditionalProposalInfo;
+	
+	private IPreferencesService fPreferenceService;
+
+	public IgnoreElementNameCompletionProposal(String pattern, int offset, String displayString, String additionalProposalInfo, Node target) {
+		fReplacementOffset= offset;
+		fPattern = pattern;
+		fDisplayString= displayString;
+		fAdditionalProposalInfo= additionalProposalInfo;
+		fTarget = target;
+		fPreferenceService = Platform.getPreferencesService();
+	}
+
+	/*
+	 * @see ICompletionProposal#apply(IDocument)
+	 */
+	public void apply(IDocument document) {
+		Object adapter = (fTarget instanceof IAdaptable ? ((IAdaptable)fTarget).getAdapter(IResource.class) : null);
+		IProject project = (adapter instanceof IResource ? ((IResource)adapter).getProject() : null);
+
+		IScopeContext[] fLookupOrder = new IScopeContext[] {new InstanceScope(), new DefaultScope()};
+		boolean hasProjectSettings = false;
+		if (project != null) {
+			ProjectScope projectScope = new ProjectScope(project);
+			if(projectScope.getNode(getPreferenceNodeQualifier())
+					.getBoolean(getProjectSettingsKey(), false)) {
+				hasProjectSettings = true;
+				fLookupOrder = new IScopeContext[] {projectScope, new InstanceScope(), new DefaultScope()};
+			}
+		}
+		
+		boolean originalEnableIgnore = fPreferenceService.getBoolean(
+				getPreferenceNodeQualifier(), HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES, 
+				HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES_DEFAULT, fLookupOrder);
+		
+		String originalElementNames = fPreferenceService.getString(
+				getPreferenceNodeQualifier(), HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE, 
+				HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE_DEFAULT, fLookupOrder);
+		
+		StringBuffer ignoreList = new StringBuffer(originalElementNames);
+	
+		if (!containsPattern(originalElementNames, fPattern)) { 
+			if (ignoreList.length() > 0)
+				ignoreList.append(',');
+			
+			ignoreList.append(fPattern.toLowerCase());
+		}
+
+		fLookupOrder[0].getNode(getPreferenceNodeQualifier())
+			.putBoolean(HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES, true); 
+
+		fLookupOrder[0].getNode(getPreferenceNodeQualifier())
+			.put(HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE, ignoreList.toString()); 
+
+		PreferenceDialog dialog = hasProjectSettings ? 
+				PreferencesUtil.createPropertyDialogOn(getShell(), project, HTMLValidationPreferencePage.PROPERTY_PAGE_ID, null, null) :
+					PreferencesUtil.createPreferenceDialogOn(getShell(), HTMLValidationPreferencePage.PREFERENCE_PAGE_ID, null, null);
+
+		int result = Window.CANCEL;
+		if (dialog != null) {
+			Object page = dialog.getSelectedPage();
+			if (page instanceof HTMLValidationPreferencePage) {
+				((HTMLValidationPreferencePage)page).overrideIgnoredElementsOriginValues(originalEnableIgnore, originalElementNames);
+			}
+			result = dialog.open();
+		}
+
+		if (Window.CANCEL == result) {
+			fLookupOrder[0].getNode(getPreferenceNodeQualifier())
+			.putBoolean(HTMLCorePreferenceNames.IGNORE_ELEMENT_NAMES, originalEnableIgnore); 
+
+			fLookupOrder[0].getNode(getPreferenceNodeQualifier())
+				.put(HTMLCorePreferenceNames.ELEMENT_NAMES_TO_IGNORE, originalElementNames); 
+		
+			for(int i = 0; i < fLookupOrder.length; i++) {
+				try {
+					fLookupOrder[i].getNode(getPreferenceNodeQualifier()).flush();
+				} catch (BackingStoreException e) {
+					Logger.logException(e);
+				}
+			}
+		}
+	}
+	
+	private boolean containsPattern(String ignoreList, String pattern) {
+		Set result = new HashSet();
+		if (ignoreList.trim().length() > 0) {
+			String[] names = ignoreList.split(","); //$NON-NLS-1$
+			for (int i = 0; names != null && i < names.length; i++) {
+				String name = names[i] == null ? null : names[i].trim();
+				if (name != null && name.length() > 0) 
+					result.add(name.toLowerCase());
+			}
+		}
+		return result.contains(pattern.toLowerCase());
+	}
+
+	
+	/*
+	 * @see ICompletionProposal#getDisplayString()
+	 */
+	public String getDisplayString() {
+		if (fDisplayString != null)
+			return fDisplayString;
+		return ""; //$NON-NLS-1$
+	}
+
+	/*
+	 * @see ICompletionProposal#getAdditionalProposalInfo()
+	 */
+	public String getAdditionalProposalInfo() {
+		return fAdditionalProposalInfo;
+	}
+
+	/*
+	 * @see ICompletionProposal#getImage()
+	 */
+	public Image getImage() {
+		return HTMLEditorPluginImageHelper.getInstance().getImage(HTMLEditorPluginImages.IMG_DTOOL_DO_NOT_VALIDATE);
+	}
+
+	/*
+	 * @see ICompletionProposal#getSelection(IDocument)
+	 */
+	public Point getSelection(IDocument document) {
+		return new Point(fReplacementOffset /*+ fCursorPosition*/, 0);
+	}
+
+	/*
+	 * @see ICompletionProposal#getContextInformation()
+	 */
+	public IContextInformation getContextInformation() {
+		return fContextInformation;
+	}
+
+	/*
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	public boolean equals(Object obj) {
+		if (obj instanceof IgnoreElementNameCompletionProposal) {
+			IgnoreElementNameCompletionProposal p = (IgnoreElementNameCompletionProposal)obj;
+			return (this.fPattern.equals(p.fPattern) && this.fTarget == p.fTarget && this.fReplacementOffset == p.fReplacementOffset);
+		}
+		return false;
+	}
+	
+	private String getPreferenceNodeQualifier() {
+		return HTMLCorePlugin.getDefault().getBundle().getSymbolicName();
+	}
+
+	private String getProjectSettingsKey() {
+		return HTMLCorePreferenceNames.USE_PROJECT_SETTINGS;
+	}
+	
+	private Shell getShell() {
+		IWorkbench workBench = HTMLUIPlugin.getDefault().getWorkbench();
+		IWorkbenchWindow workBenchWindow = workBench == null ? null : workBench.getActiveWorkbenchWindow();
+		return workBenchWindow == null ? null : workBenchWindow.getShell();
+	}
+}
-- 
1.9.3

