Skip to content

Commit ae014a5

Browse files
Create App-Main.py
1 parent b0ad786 commit ae014a5

File tree

1 file changed

+312
-0
lines changed

1 file changed

+312
-0
lines changed

App-Main.py

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
import tkinter as tk
2+
from tkinter import ttk, messagebox, scrolledtext
3+
import pyperclip # Used for the copy-to-clipboard feature
4+
import datetime # For timestamp generation
5+
6+
# --- JavaScript Generation Functions ---
7+
8+
def generate_select_element(selector_type, selector_value):
9+
"""Generates JS code to select an element."""
10+
if not selector_value:
11+
return "// Error: Selector value cannot be empty."
12+
if selector_type == "ID":
13+
return f"const element = document.getElementById('{selector_value}');"
14+
elif selector_type == "Class Name (First)":
15+
# Selects the first element with the class
16+
return f"const element = document.querySelector('.{selector_value}');"
17+
elif selector_type == "Tag Name (First)":
18+
# Selects the first element with the tag name
19+
return f"const element = document.querySelector('{selector_value}');"
20+
else:
21+
return "// Error: Invalid selector type."
22+
23+
def generate_event_listener(element_id, event_type, function_body=""):
24+
"""Generates JS code for an event listener."""
25+
if not element_id or not event_type:
26+
return "// Error: Element ID and Event Type are required."
27+
28+
# Basic indentation for the function body placeholder
29+
indented_body = "\n // Your code here...\n"
30+
if function_body.strip():
31+
indented_body = "\n" + "\n".join([" " + line for line in function_body.splitlines()]) + "\n"
32+
33+
return f"""
34+
const element_{element_id} = document.getElementById('{element_id}');
35+
36+
if (element_{element_id}) {{
37+
element_{element_id}.addEventListener('{event_type}', function(event) {{
38+
// 'event' object contains information about the event
39+
console.log('{event_type} triggered on element with ID: {element_id}');{indented_body}
40+
}});
41+
}} else {{
42+
console.error('Element with ID "{element_id}" not found.');
43+
}}
44+
"""
45+
46+
def generate_change_content(element_id, content_type, new_content):
47+
"""Generates JS code to change element content."""
48+
if not element_id:
49+
return "// Error: Element ID is required."
50+
prop = 'textContent' if content_type == 'Text Content' else 'innerHTML'
51+
# Escape backticks and backslashes in the content for template literals
52+
escaped_content = new_content.replace('\\', '\\\\').replace('`', '\\`')
53+
return f"""
54+
const element_{element_id}_content = document.getElementById('{element_id}');
55+
56+
if (element_{element_id}_content) {{
57+
element_{element_id}_content.{prop} = `{escaped_content}`;
58+
}} else {{
59+
console.error('Element with ID "{element_id}" not found for changing content.');
60+
}}
61+
"""
62+
63+
def generate_change_style(element_id, style_prop, style_value):
64+
"""Generates JS code to change element style."""
65+
if not element_id or not style_prop or not style_value:
66+
return "// Error: Element ID, Style Property, and Style Value are required."
67+
# Convert CSS property from dash-case to camelCase if needed
68+
if '-' in style_prop:
69+
js_style_prop = ''.join(word.capitalize() for word in style_prop.split('-'))
70+
js_style_prop = js_style_prop[0].lower() + js_style_prop[1:]
71+
else:
72+
js_style_prop = style_prop
73+
return f"""
74+
const element_{element_id}_style = document.getElementById('{element_id}');
75+
76+
if (element_{element_id}_style) {{
77+
element_{element_id}_style.style.{js_style_prop} = '{style_value}';
78+
}} else {{
79+
console.error('Element with ID "{element_id}" not found for changing style.');
80+
}}
81+
"""
82+
83+
def generate_function_definition(func_name, params_str, function_body=""):
84+
"""Generates a basic JS function definition."""
85+
if not func_name:
86+
return "// Error: Function Name is required."
87+
# Basic validation for function name
88+
if not func_name.isidentifier() or func_name in ['function', 'var', 'let', 'const']:
89+
return f"// Error: '{func_name}' is not a valid JavaScript function name."
90+
91+
# Basic indentation for the function body placeholder
92+
indented_body = "\n // Your function logic here...\n"
93+
if function_body.strip():
94+
indented_body = "\n" + "\n".join([" " + line for line in function_body.splitlines()]) + "\n"
95+
96+
return f"""
97+
function {func_name}({params_str}) {{
98+
console.log('Function {func_name} called with parameters: ' + Array.from(arguments).join(', '));{indented_body}
99+
// return result; // Optional return statement
100+
}}
101+
102+
// Example usage (optional):
103+
// {func_name}(/* provide arguments here */);
104+
"""
105+
106+
# --- GUI Application Class ---
107+
108+
class JsGeneratorApp:
109+
def __init__(self, master):
110+
self.master = master
111+
master.title("JavaScript Snippet Generator")
112+
master.geometry("650x600") # Adjusted size
113+
114+
# Style configuration
115+
style = ttk.Style()
116+
style.theme_use('clam') # Use a theme that looks better on Windows
117+
style.configure("TLabel", padding=5, font=('Helvetica', 10))
118+
style.configure("TButton", padding=5, font=('Helvetica', 10))
119+
style.configure("TEntry", padding=5, font=('Helvetica', 10))
120+
style.configure("TCombobox", padding=5, font=('Helvetica', 10))
121+
122+
# --- Top Frame: Task Selection ---
123+
self.top_frame = ttk.Frame(master, padding="10")
124+
self.top_frame.pack(fill=tk.X)
125+
126+
self.task_label = ttk.Label(self.top_frame, text="Select JavaScript Task:")
127+
self.task_label.pack(side=tk.LEFT, padx=(0, 10))
128+
129+
self.task_options = [
130+
"Select Element",
131+
"Add Event Listener",
132+
"Change Element Content",
133+
"Change Element Style",
134+
"Define Basic Function"
135+
]
136+
self.selected_task = tk.StringVar()
137+
self.task_combobox = ttk.Combobox(self.top_frame, textvariable=self.selected_task,
138+
values=self.task_options, state="readonly", width=30)
139+
self.task_combobox.pack(side=tk.LEFT, fill=tk.X, expand=True)
140+
self.task_combobox.current(0) # Default selection
141+
self.task_combobox.bind("<<ComboboxSelected>>", self.update_input_fields)
142+
143+
# --- Middle Frame: Dynamic Inputs ---
144+
self.input_frame = ttk.Frame(master, padding="10")
145+
self.input_frame.pack(fill=tk.BOTH, expand=True)
146+
self.input_widgets = {} # To keep track of dynamic widgets
147+
148+
# --- Bottom Frame: Output and Actions ---
149+
self.bottom_frame = ttk.Frame(master, padding="10")
150+
self.bottom_frame.pack(fill=tk.X)
151+
152+
self.generate_button = ttk.Button(self.bottom_frame, text="Generate Code", command=self.generate_code)
153+
self.generate_button.pack(side=tk.LEFT, padx=(0, 10))
154+
155+
self.copy_button = ttk.Button(self.bottom_frame, text="Copy to Clipboard", command=self.copy_to_clipboard)
156+
self.copy_button.pack(side=tk.LEFT)
157+
158+
# --- Output Text Area ---
159+
self.output_label = ttk.Label(master, text="Generated JavaScript:", padding=(10, 5, 10, 0))
160+
self.output_label.pack(fill=tk.X)
161+
162+
self.output_text = scrolledtext.ScrolledText(master, height=15, width=70, wrap=tk.WORD,
163+
font=("Courier New", 10), relief=tk.SUNKEN, borderwidth=1)
164+
self.output_text.pack(padx=10, pady=(0, 10), fill=tk.BOTH, expand=True)
165+
self.output_text.insert(tk.END, "// Select a task and provide inputs to generate JavaScript code.")
166+
self.output_text.configure(state='disabled') # Make read-only initially
167+
168+
# Initial setup
169+
self.update_input_fields() # Populate inputs for the default task
170+
171+
def clear_input_frame(self):
172+
"""Removes all widgets from the input frame."""
173+
for widget in self.input_frame.winfo_children():
174+
widget.destroy()
175+
self.input_widgets = {}
176+
177+
def add_input_field(self, label_text, key, widget_type='entry', options=None, text_height=3):
178+
"""Adds a labeled input field to the input frame."""
179+
frame = ttk.Frame(self.input_frame)
180+
frame.pack(fill=tk.X, pady=2)
181+
182+
label = ttk.Label(frame, text=label_text, width=18, anchor="w")
183+
label.pack(side=tk.LEFT, padx=(0, 5))
184+
185+
if widget_type == 'entry':
186+
widget = ttk.Entry(frame)
187+
widget.pack(side=tk.LEFT, fill=tk.X, expand=True)
188+
elif widget_type == 'combobox':
189+
var = tk.StringVar()
190+
# For combobox, set state to "normal" to allow free text input
191+
widget = ttk.Combobox(frame, textvariable=var, values=options, state="normal")
192+
if options:
193+
widget.current(0)
194+
widget.pack(side=tk.LEFT, fill=tk.X, expand=True)
195+
self.input_widgets[key + '_var'] = var # Store the variable too
196+
elif widget_type == 'textarea':
197+
widget = tk.Text(frame, height=text_height, width=40, relief=tk.SUNKEN, borderwidth=1, font=('Helvetica', 10))
198+
widget.pack(side=tk.LEFT, fill=tk.X, expand=True)
199+
200+
self.input_widgets[key] = widget
201+
202+
def update_input_fields(self, event=None):
203+
"""Updates the input fields based on the selected task."""
204+
self.clear_input_frame()
205+
task = self.selected_task.get()
206+
207+
if task == "Select Element":
208+
self.add_input_field("Selector Type:", "selector_type", widget_type='combobox',
209+
options=["ID", "Class Name (First)", "Tag Name (First)"])
210+
self.add_input_field("Selector Value:", "selector_value")
211+
elif task == "Add Event Listener":
212+
self.add_input_field("Element ID:", "element_id")
213+
self.add_input_field("Event Type:", "event_type", widget_type='combobox',
214+
options=["click", "mouseover", "mouseout", "keydown", "submit", "change", "load"])
215+
self.add_input_field("Function Body (Optional):", "function_body", widget_type='textarea', text_height=4)
216+
elif task == "Change Element Content":
217+
self.add_input_field("Element ID:", "element_id")
218+
self.add_input_field("Content Type:", "content_type", widget_type='combobox',
219+
options=["Text Content", "HTML Content"])
220+
self.add_input_field("New Content:", "new_content", widget_type='textarea', text_height=4)
221+
elif task == "Change Element Style":
222+
self.add_input_field("Element ID:", "element_id")
223+
self.add_input_field("CSS Property:", "style_prop", widget_type='combobox',
224+
options=['color', 'background-color', 'font-size', 'display', 'border', 'padding', 'margin'])
225+
self.add_input_field("Style Value:", "style_value")
226+
elif task == "Define Basic Function":
227+
self.add_input_field("Function Name:", "func_name")
228+
self.add_input_field("Parameters (comma-sep):", "params_str")
229+
self.add_input_field("Function Body (Optional):", "function_body", widget_type='textarea', text_height=5)
230+
231+
# Clear previous output
232+
self.output_text.configure(state='normal')
233+
self.output_text.delete('1.0', tk.END)
234+
self.output_text.insert(tk.END, "// Provide inputs above and click 'Generate Code'.")
235+
self.output_text.configure(state='disabled')
236+
237+
def get_input_value(self, key, widget_type='entry'):
238+
"""Safely gets the value from an input widget."""
239+
widget = self.input_widgets.get(key)
240+
if not widget:
241+
return None
242+
243+
if widget_type == 'entry':
244+
return widget.get().strip()
245+
elif widget_type == 'combobox':
246+
var = self.input_widgets.get(key + '_var')
247+
return var.get() if var else None
248+
elif widget_type == 'textarea':
249+
return widget.get("1.0", tk.END).strip()
250+
251+
return None
252+
253+
def generate_code(self):
254+
"""Generates the JavaScript code based on inputs."""
255+
task = self.selected_task.get()
256+
js_code = f"// Code generation for task: {task}\n// Timestamp: {datetime.datetime.now()}\n\n"
257+
258+
try:
259+
if task == "Select Element":
260+
selector_type = self.get_input_value("selector_type", 'combobox')
261+
selector_value = self.get_input_value("selector_value")
262+
js_code += generate_select_element(selector_type, selector_value)
263+
elif task == "Add Event Listener":
264+
element_id = self.get_input_value("element_id")
265+
event_type = self.get_input_value("event_type", 'combobox')
266+
function_body = self.get_input_value("function_body", 'textarea')
267+
js_code += generate_event_listener(element_id, event_type, function_body)
268+
elif task == "Change Element Content":
269+
element_id = self.get_input_value("element_id")
270+
content_type = self.get_input_value("content_type", 'combobox')
271+
new_content = self.get_input_value("new_content", 'textarea')
272+
js_code += generate_change_content(element_id, content_type, new_content)
273+
elif task == "Change Element Style":
274+
element_id = self.get_input_value("element_id")
275+
style_prop = self.get_input_value("style_prop")
276+
style_value = self.get_input_value("style_value")
277+
js_code += generate_change_style(element_id, style_prop, style_value)
278+
elif task == "Define Basic Function":
279+
func_name = self.get_input_value("func_name")
280+
params_str = self.get_input_value("params_str")
281+
function_body = self.get_input_value("function_body", 'textarea')
282+
js_code += generate_function_definition(func_name, params_str, function_body)
283+
else:
284+
js_code += "// Task not yet implemented."
285+
except Exception as e:
286+
js_code += f"\n// An error occurred during code generation: {e}"
287+
messagebox.showerror("Generation Error", f"An unexpected error occurred:\n{e}")
288+
289+
self.output_text.configure(state='normal')
290+
self.output_text.delete('1.0', tk.END)
291+
self.output_text.insert('1.0', js_code)
292+
self.output_text.configure(state='disabled')
293+
294+
def copy_to_clipboard(self):
295+
"""Copies the generated code to the clipboard."""
296+
code = self.output_text.get('1.0', tk.END).strip()
297+
if code and not code.startswith("// Provide inputs"):
298+
try:
299+
pyperclip.copy(code)
300+
messagebox.showinfo("Copied", "JavaScript code copied to clipboard!")
301+
except pyperclip.PyperclipException as e:
302+
messagebox.showwarning("Copy Error", f"Could not copy to clipboard:\n{e}\n\nYou may need to install the 'pyperclip' library:\n pip install pyperclip")
303+
except Exception as e:
304+
messagebox.showerror("Error", f"An unexpected error occurred during copy:\n{e}")
305+
else:
306+
messagebox.showwarning("Nothing to Copy", "Generate some code first.")
307+
308+
# --- Main Execution ---
309+
if __name__ == "__main__":
310+
root = tk.Tk()
311+
app = JsGeneratorApp(root)
312+
root.mainloop()

0 commit comments

Comments
 (0)